Dynamic static method call in PHP?

73,582

Solution 1

Use the call_user_func function:

http://php.net/manual/en/function.call-user-func.php

Example:

call_user_func('myClassName_' . $language . '::myFunctionName');

Solution 2

I think you could do:

$classname = 'myClassName_' . $language;
$result = $classname::myFunctionName();

This is called Variable Functions

Solution 3

I would encapsulate the creation of the class you need in a factory.

This way you will have a single entry point when you need to change your base name or the rules for mapping the language to the right class.

    class YourClassFactory {

        private $_language;
        private $_basename = 'yourclass';

        public YourClassFactory($language) {
            $this->_language = $language;
        }

        public function getYourClass() {
            return $this->_basename . '_' . $this->_language;
        }    
    } 

and then, when you have to use it:

$yourClass = $yourClassFactoryInstance->getYourClass();
$yourClass::myFunctionName();

Solution 4

As temuri said, parse error is produced, when trying '$className::functionName' :

Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM ...

In my case (static method with 2 arguments), best solutions is to use call_user_func_array with 2 arrays (as suggested by nikc.org):

$result = call_user_func_array(array($className, $methodName), array($ard1, $arg2));

BR

Solution 5

although i think the way you deal is a very bad idea, i think i may have a solution

$className = 'myClassName_'.$language;
$result = $className::myFunctionName();

i think this is what you want

Share:
73,582
Tom
Author by

Tom

I'm just here to look at the pictures.

Updated on July 05, 2022

Comments

  • Tom
    Tom almost 2 years

    Please could someone experienced in PHP help out with the following. Somewhere in my code, I have a call to a public static method inside a non-instantiated class:

    $result = myClassName::myFunctionName();
    

    However, I would like to have many such classes and determine the correct class name on the fly according to the user's language. In other words, I have:

    $language = 'EN';
    

    ... and I need to do something like:

    $result = myClassName_EN::myFunctionName();
    

    I know I could pass the language as a parameter to the function and deal with it inside just one common class but for various reasons, I would prefer a different solution.

    Does this make any sense, anyone? Thanks.

  • Tom
    Tom over 14 years
    Please could you tell me why it's such a bad idea?
  • nikc.org
    nikc.org over 14 years
    Combined with is_callable and method_exists this would be my recommandation as well. To pass params look at call_user_func_array php.net/is_callable php.net/method_exists php.net/call_user_func_array
  • ahmetunal
    ahmetunal over 14 years
    you can use language as a parameter, instead you choose to define a new class for it. Say you wanna support 200 different languages, will you sit and write 200 different classes. Also it will make your code extremely difficult to read and understand.
  • Tom
    Tom over 14 years
    Ah.... no there won't be 200 languages. It's a conscious downgrade of good practice to get something else done in a more practical way.
  • Tom
    Tom over 14 years
    This sort of works and seems like the cleanest solution. Thanks
  • penetra
    penetra over 13 years
    Only in <5.3.0 is this not allowed. Over 5.3.0 it is allowed.
  • tftd
    tftd about 13 years
  • Nick Redmark
    Nick Redmark almost 13 years
    just a note: this works only since php 5.3 - better check if your host provider supports that version (the one I'm using doesn't).
  • btleffler
    btleffler about 10 years
    @nikc.org You can also pass parameters directly to call_user_func() if compiling them into an array is inconvenient.
  • Olivier de Jonge
    Olivier de Jonge over 9 years
    Won't work. Calls a user defined function or method given by the function parameter, with the following arguments. This function must be called within a method context, it can't be used outside a class... as mentioned in php.net/manual/en/function.forward-static-call.php
  • fred727
    fred727 over 8 years
    For me, this is the best solution. And according to my bench, this is the quickest too : 100.000 iterations took 0.28s with direct call, 0.32 with this solution, and 0.47 with call_user_func
  • Felipe Francisco
    Felipe Francisco over 8 years
    Is there a way to do this using ReflectionMethod class?
  • Josh Foskett
    Josh Foskett over 7 years
    It should be noted that you can also format it like this: call_user_func(['myClassName_' . $language, 'myFunctionName']);
  • Uncoke
    Uncoke about 5 years
    Here more info how the Factory Method Design Pattern works: sitepoint.com/understanding-the-factory-method-design-patter‌​n
  • Amitesh Bharti
    Amitesh Bharti over 2 years
    sometimes we need a fully qualified class name then use this way to add the namespace in the class $className = '\\QuickBooksOnline\\API\Facades\\'.$resource; $postPayload = $className::create();