call_user_func_array
Calls a callable with its arguments supplied as an array, positional or named.
call_user_func_array(callable $callback, array $args): mixed- Added in PHP 4.0.4
Parameters
| Parameter | Type | Description |
|---|---|---|
$callback | callable | The callable to invoke. |
$args | array | The arguments for the callback. Integer keys are passed positionally in array order; string keys are passed as named arguments matching parameter names. |
Return value
mixedThe value returned by the callback.
Errors
Throws a TypeError if callback is not callable, and an Error if a string key does not match any parameter name or an integer key follows a string key.
Changelog
- PHP 8.0String keys in args are now interpreted as parameter names (named arguments) instead of being silently ignored.
- PHP 8.0An invalid callback now throws a TypeError instead of raising a warning and returning false.
call_user_func_array() is the variant of call_user_func() you use when the argument list itself lives in an array: a queued job whose payload was decoded from JSON, a middleware chain forwarding whatever it was given, a test helper that replays recorded calls.
The PHP 8 change that bites
Before PHP 8, string keys in the argument array were ignored and the values passed positionally. Since PHP 8 a string key means a named argument. Code that passed an associative array by accident and got away with it now fails loudly with an Error if the key is not a real parameter name. If you want the old positional behaviour from an associative array, run it through array_values() first.
Prefer the spread operator
In modern code $callback(...$args) does the same job with less indirection, and it also understands string keys as named arguments. call_user_func_array() stays useful mainly for callables expressed as strings and for older codebases.
References
Unlike call_user_func(), this function can pass by reference, but only if the element inside the argument array was itself created as a reference.
Example
When to use it
- Replaying a queued job whose handler name and argument list were stored as data
- Forwarding an unknown argument list from a __call() magic method to a real method
- Calling a function whose arguments were decoded from a JSON request payload
- Applying named arguments built dynamically from a configuration array
Frequently asked questions
What is the difference between call_user_func and call_user_func_array?
call_user_func() takes arguments one by one after the callback, while call_user_func_array() takes them as a single array. Use the array form when the argument list is data you received rather than something you wrote out.
Why does call_user_func_array throw an Error with an associative array in PHP 8?
Since PHP 8.0, string keys are treated as named arguments, so a key that does not match a parameter name is an error. Pass array_values($args) if the keys were meaningless labels.
Does call_user_func_array preserve the order of the array?
Yes for integer keys: elements are passed positionally in array order, and the actual key numbers are ignored. String-keyed elements are matched by parameter name instead of position.
More examples
Wrapping any call with logging
Prints the argument count before each call, then 9 and a-b-c. The wrapper never needs to know the arity of the function it forwards to, which is the whole point of taking the arguments as an array.
<?php
function logged(callable $fn, array $args): mixed
{
echo 'calling with ', count($args), " argument(s)\n";
return call_user_func_array($fn, $args);
}
echo logged('max', [3, 9, 4]), "\n";
echo logged('implode', ['-', ['a', 'b', 'c']]), "\n";The spread operator does the same thing
All three lines produce 12, 12 and 10. The spread operator handles both positional and string-keyed arrays, so in new code it can usually replace call_user_func_array() entirely.
<?php
function area(float $w, float $h): float { return $w * $h; }
$args = [3.0, 4.0];
echo call_user_func_array('area', $args), "\n";
echo area(...$args), "\n";
$byName = ['h' => 2.0, 'w' => 5.0];
echo area(...$byName), "\n";Passing an argument by reference
Prints Array ( [0] => a [1] => b ). The modification survives only because $args[0] was created as a reference with &$stack; without the ampersand PHP 8 raises an Error about the argument not being passable by reference.
<?php
function push(array &$stack, string $item): void { $stack[] = $item; }
$stack = ['a'];
$args = [&$stack, 'b'];
call_user_func_array('push', $args);
print_r($stack);
Discussion