Named functions, anonymous functions, static methods, instance methods, and objects using the __invoke method are collectively called callables. If I have a callable, it can be called by putting the brackets after that "()" (I assume it takes no arguments). This works when our called is stored in a variable, for example:
$f(); // Call $f
However, what if I store the called in the property of the object?
$obj = new stdClass; $obj->my_func = function() {}; $obj->my_func();
The problem is that the PHP parser is confused because the code is ambiguous, this may mean invoking a property being called or invoking a method. PHP prefers to always consider this type of code as a method call, so we cannot invoke called properties this way. This is why we need "call_user_func":
call_user_func($obj->my_func);
There are other cases where PHP does not understand the syntax of ordinary brackets; for example, PHP currently (5.5) does not know how to call the return value of another called:
get_a_callable()(); // Parse error, unexpected "(" call_user_func(get_a_callable()); // Calls the return value of get_a_callable
It is also currently not possible to call the definition function directly, which is useful for working with PHP when "let" statements are missing, for example:
function($x) { echo $x . $x; }('hello'); // Parse error, unexpected "(" call_user_func(function($x) { echo $x . $x; }, 'hello'); // Calls the function
There are also times when it is useful to have function calls / reified / as the function 'call_user_func'. For example, when using higher-order functions, such as array_map:
$funcs = [function() { return 'hello'; }, function() { return 'world'; }]; array_map('call_user_func', $funcs);
It is also useful when we do not know how many parameters are required, i.e. we cannot replace our own function ($ f, $ x, $ y, ...) {return $ f ($ x, $ y, ...);} ".
One of the particularly good definitions is a partial application that takes up just a few lines thanks to the calls to_user_func and call_user_func_array:
function partial() { $args1 = func_get_args(); // $f, $a, $b, $c, ... return function() use ($args1) { // Returns $f($a, $b, $c, ..., $d, $e, $f, ...) $args2 = func_get_args(); // $d, $e, $f, ... return call_user_func_array('call_user_func', array_merge($args1, $args2)); }; }