All the Dynamic Syntaxes
in PHP
In PHP, dynamic calls happens when the call will get at least one of its expression’s elements (and sometimes, even all of them) at execution time. They are not known at coding time, so there are usually some variables involved in the matter.
Interestingly, there are very little expressions that cannot be called dynamically in PHP. Let’s review them:
- Variables
- One of the most famous syntax:
$$var
, where$var
should contain a string with a valid variable name, which will be used as the name of the second variable. This way,$a = 'b'; $b = 'c'; echo $$a;
displaysc
;
- One of the most famous syntax:
- Functions
- This one is also quite famous: the function name should be in the variable.
$function = 'foo'; $function()
will call thefoo
function. Note that the full name of the function should be used, as no replacement will happen with theuse
expressions;
- This one is also quite famous: the function name should be in the variable.
- Constants
- This one is a bit tricky, since constants have such a simple syntax. To dynamically call a constant, you need to use the
constant()
function.$a = 'E_ALL'; echo constant($a);
will do the job.
- This one is a bit tricky, since constants have such a simple syntax. To dynamically call a constant, you need to use the
- Instantiation
- Instantiation may also use a variable, just like for function.
$classname = '
\A\B’; $object = new $classname()`;
- Instantiation may also use a variable, just like for function.
- Instanceof
- Instanceof checks if a variable contains an object of a certain class. The class name is the second argument, and it may very well be a variable.
$object instanceof $myClass::class
.
- Instanceof checks if a variable contains an object of a certain class. The class name is the second argument, and it may very well be a variable.
- namespaces
- Not all namespaces may be dynamic, but some. In particular, the
namespaces MySpace
, at the beginning of every PHP scripts nowadays, cannot be changed. I also hope this will stay as it is. - On the other hand, it is possible to create new namespaces on the fly. Either with define(), to create a constant in a non-existing namespace : it will then be created.
define('\A\B', 1);
creates a new namespace and a new constant. - Then, the same is also possible with classes, and their cousins (interfaces, traits, enums), with class_alias(). Contrary to define(), it will only copy an existing class. Yet, it creates new namespaces too.
- As for functions, I am not aware of any ways to create them on the fly. Yes, I know, closures and arrow functions, but they are anonymous.
- Last tidbit for dynamic namespaces, this time when calling it. It is possible to use the
namespace
keyword in when calling anything, and make sure that the call happens inside the current namespace. So, `echo namespace\E_ALL;’ will always fail, unless this code is already in the global namespace.
- Not all namespaces may be dynamic, but some. In particular, the
- Methods
- Methods works just like functions, except that you need the object first. `$method = ‘m’; $object->$method();’
- Properties
- Properties works just like methods. This time though, case is important. `$property = ‘p’; $object->$p;’ Note that it looks like a weird static call.
- It is also possible to call statically a property and dynamically re-route it to another. This is achieved with the magic methods
__get()
and__set()
.
- Class constants
- Class constants may actually be turned into a non-constant value, simply by using an object as the ‘class’ part. So,
echo $object::CONSTANT
will literally be resolved at execution time, even though it is a constant. - Note also that the constant part of the class constant syntax cannot be made into a variable, since it will confuse the parser with a static property. So, the solution is to revert to the constant() function, as a string or a
- Class constants may actually be turned into a non-constant value, simply by using an object as the ‘class’ part. So,
- Arguments
- Arguments are the second part of the methods or function call. For those, there are even two different syntax. Either with a function, such as
call_user_func
orcall_user_func_array
, which take the function name as first argument, and the arguments as the next arguments (sic). - The second syntax is the ellipsis argument. The ‘three dots’ operators spreads the elements of the array, just like we would write is in the code.
$function(...$args)
- Arguments are the second part of the methods or function call. For those, there are even two different syntax. Either with a function, such as
- Arguments reception
- Arguments may not be defined in the method signature. When you need to handle an arbitrary number of arguments, there are
func_get_args()
, which allow the access to the incoming arguments.
- Arguments may not be defined in the method signature. When you need to handle an arbitrary number of arguments, there are
- Eval()
- The ultimate dynamic code of all, is the eval() function. It takes a string of PHP, and executes it. This opens the door to huge freedom and great responsibility. And, since we have covered all other syntax to dynamically call anything, it is actually pretty useless.
Some elements do no have any dynamic syntax: type hints, class extensions, use expressions or most of the operators. Operators often have a function equivalent (think, ** versus pow()), so falling back to functions is a good way to go.
Most of those dynamic calls come with big red warnings: in terms of security, every dynamic element should be checked before usage, to avoid problems of existence, or nefarious redirections. And, there is also a speed penalty, as PHP has to wait for execution time to actually do the work. Think, const versus define().