function foobar($arg, $arg2) {
echo __FUNCTION__, " got $arg and $arg2\n";
}
foobar('one','two'); // OUTPUTS : foobar got one and two
call_user_func_array("foobar", array("one", "two")); // // OUTPUTS : foobar got one and two
As I can see both regular one and call_user_func_array
method both outputs same, then why should one prefer it?
In which scenario regular calling method will fail but call_user_func_array
will not?
Can I get any such example?
Thank you
If you don't know beforehand how many arguments you're going to pass to your function, it would be advisable to use
call_user_func_array()
; the only alternative is aswitch
statement or a bunch of conditions to accomplish a predefined subset of possibilities.Another scenario is where the function to be called is not known beforehand, e.g.
array($obj, 'method')
; this is also where you could usecall_user_func()
.Note that using
call_user_func_*
functions can't be used to call private or protected methods.The alternative to all of this is to make your functions accept an array as its only argument:
However, this eliminates the possibility to type-hint each argument in your function declaration and is generally considered a code smell.
call_user_func_array
performs "uncurrying", which is the opposite of "currying".The following applies to all of PHP's "callables" (named functions, closures, methods,
__invoke
, etc.), so for simplicity let's ignore the differences and just focus on closures.If we want to accept multiple arguments, PHP lets us do that with 3 different APIs. The usual way is this:
Another way is called curried form:
The advantage is that all curried functions can be called in the same way: give them one argument.
If more arguments are required, more curried functions are returned, which 'remember' the previous arguments. This allows us to pass in some arguments now and the rest later.
There are some problems with this:
We can fix all of these issues by using a conversion function (disclaimer: that's my blog). This lets us write and call our functions in the usual way, but gives them the same 'memory' ability as if they were curried:
The third way is called uncurried and takes all of its arguments in one:
Just like with curried functions, uncurried functions can all be called with one argument, although this time it's an array. We still face the same compatibility problems as curried functions: if we choose to use uncurried functions, we can't rely on everyone else choosing the same. Hence we also need a conversion function for uncurrying. That's what
call_user_func_array
does:Interestingly, we can get rid of that extra
function($args)
wrapper (a process known as "eta-reduction") by curryingcall_user_func_array
:Unfortunately
call_user_func_array
isn't as smart ascurry
; it won't automatically convert between the two. We can write our ownuncurry
function which has that ability:These conversion functions show that PHP's "usual" way of defining functions is actually redundant: if we replaced PHP's "usual" functions with 'smart' curried or uncurried ones, lots of code would carry on working. If we did that, it's better to curry everything and selectively uncurry as needed, since that's easier than going the other way around.
Unfortunately, some things which expect a variable number of arguments using
func_get_args
would break, as well as functions with default argument values.Interestingly, default values are just a special form of currying. We could mostly do without them if we put those arguments first instead of last, and provided a bunch of alternative definitions which curry in the defaults. For example:
You should prefer calling the function as you'd do regularly. Use
call_user_func_array
with dynamic arguments. For example:As of php 5.6, to pass an array instead of an argument list to a function simply precede the array with an ellipsis (this is called "argument unpacking").
The difference between
call_user_func_array()
and variable functions as of php 5.6 is that variable functions do not allow you to call a static method:Php 7 adds the ability to call static methods via a variable function, so as of php 7 this difference no longer exists. In conclusion,
call_user_func_array()
gives your code greater compatibility.You have an array with the arguments for your function which is of indeterminate length.
The alternative would be:
Which is not a solution.
The use case for this may be rare, but when you come across it you need it.