How to call a function from a string stored in a variable?
Solution: Use PHP7
Note: For a summarized version, see TL;DR at the end of the answer.
Old Methods
Update: One of the old methods explained here has been removed. Refer to other answers for explanation on other methods, it isn't covered here. By the way, if this answer doesn't help you, you should return upgrading your stuff. PHP 5.6 support has ended in January 2019 (now even PHP 7.2 and 7.3 are not being supported). See supported versions for more information.
As others mentioned, in PHP5 (and also in newer versions like PHP7) we could use variables as function names, use call_user_func()
and call_user_func_array()
, etc.
New Methods
As of PHP7, there are new ways introduced:
Note: Everything inside <something>
brackets means one or more expressions to form something, e.g. <function_name>
means expressions forming a function name.
Dynamic Function Call: Function Name On-the-fly
We can form a function name inside parentheses in just one go:
(<function_name>)(arguments);
For example:
function something(): string
{
return "something";
}
$bar = "some_thing";
(str_replace("_", "", $bar))(); // something
// Possible, too; but generally, not recommended, because makes your
// code more complicated
(str_replace("_", "", $bar))()();
Note: Although removing the parentheses around str_replace()
is not an error, putting parentheses makes code more readable. However, you cannot do that sometimes, e.g. while using .
operator. To be consistent, I recommend you to put the parentheses always.
Dynamic Function Call: Callable Property
A useful example would be in the context of objects: If you have stored a callable in a property, you have to call it this way:
($object->{<property_name>})();
As a simple example:
// Suppose we're in a class method context
($this->eventHandler)();
Obviously, calling it as $this->eventHandler()
is plain wrong: By that you mean calling a method named eventHandler
.
Dynamic Method Call: Method Name On-the-fly
Just like dynamic function calls, we can do the same way with method calls, surrounded by curly braces instead of parentheses (for extra forms, navigate to TL;DR section):
$object->{<method_name>}(arguments);
$object::{<method_name>}(arguments);
See it in an example:
class Foo
{
public function another(): string
{
return "something";
}
}
$bar = "another thing";
(new Something())->{explode(" ", $bar)[0]}(); // something
Dynamic Method Call: The Array Syntax
A more elegant way added in PHP7 is the following:
[<object>, <method_name>](arguments);
[<class_name>, <method_name>](arguments); // Static calls only
As an example:
class Foo
{
public function nonStaticCall()
{
echo "Non-static call";
}
public static function staticCall()
{
echo "Static call";
}
}
$x = new X();
[$x, "non" . "StaticCall"](); // Non-static call
[$x, "static" . "Call"](); // Static call
Note: The benefit of using this method over the previous one is that, you don't care about the call type (i.e. whether it's static or not).
Note: If you care about performance (and micro-optimizations), don't use this method. As I tested, this method is really slower than other methods (more than 10 times).
Extra Example: Using Anonymous Classes
Making things a bit complicated, you could use a combination of anonymous classes and the features above:
$bar = "SomeThing";
echo (new class {
public function something()
{
return 512;
}
})->{strtolower($bar)}(); // 512
TL;DR (Conclusion)
Generally, in PHP7, using the following forms are all possible:
// Everything inside `<something>` brackets means one or more expressions
// to form something
// Dynamic function call via function name
(<function_name>)(arguments);
// Dynamic function call on a callable property
($object->{<property_name>})(arguments);
// Dynamic method call on an object
$object->{<method_name>}(arguments);
$object::{<method_name>}(arguments);
// Dynamic method call on a dynamically-generated object
(<object>)->{<method_name>}(arguments);
(<object>)::{<method_name>}(arguments);
// Dynamic method call, statically
ClassName::{<method_name>}(arguments);
(<class_name>)::{<method_name>}(arguments);
// Dynamic method call, array-like (no different between static
// and non-static calls
[<object>, <method_name>](arguments);
// Dynamic method call, array-like, statically
[<class_name>, <method_name>](arguments);
Special thanks to this PHP talk.
My favorite version is the inline version:
${"variableName"} = 12;
$className->{"propertyName"};
$className->{"methodName"}();
StaticClass::${"propertyName"};
StaticClass::{"methodName"}();
You can place variables or expressions inside the brackets too!
$functionName()
or call_user_func($functionName)