Callbacks & Callable
PHP does not have a single dedicated "function type." Instead, it recognizes several different shapes of value as "invokable," and groups them all under the pseudo-type callable. When a function's parameter is type-hinted callable, PHP will accept a plain string function name, a Closure object, an array describing an object-and- method pair, or an object with an __invoke() method. Understanding these forms matters because a lot of PHP's standard library — array_map, usort, call_user_func, and many others — is built entirely around accepting a callable rather than a fixed function.
String callables: calling a function by name
The simplest callable is just the name of a function, as a string. PHP looks it up at call time and invokes it.
A built-in function name as a callable
<?php
function applyCallback(callable $fn, string $value): string {
return $fn($value);
}
echo applyCallback('strtoupper', 'hello world');HELLO WORLD
This works for any user-defined function too, not just built-ins: applyCallback('myCustomFunction', $value) behaves the same way as long as myCustomFunction exists somewhere PHP can see it.
Array callables for methods
To reference a method rather than a standalone function, PHP uses a two-element array. For an instance method, the first element is the object and the second is the method name as a string. For a static method, the first element is the class name (or ClassName::class) instead of an object instance.
Instance-method and static-method array callables
<?php
class PriceFormatter {
private string $currency;
public function __construct(string $currency) {
$this->currency = $currency;
}
public function format(float $amount): string {
return number_format($amount, 2) . ' ' . $this->currency;
}
public static function formatCad(float $amount): string {
return number_format($amount, 2) . ' CAD';
}
}
$formatter = new PriceFormatter('EUR');
// Instance method: [$object, 'methodName']
$instanceCallable = [$formatter, 'format'];
echo $instanceCallable(1999.5), "\n";
// Static method: [ClassName::class, 'staticMethod']
$staticCallable = [PriceFormatter::class, 'formatCad'];
echo $staticCallable(1999.5), "\n";1,999.50 EUR 1,999.50 CAD
A static method callable can also be written as the single string 'PriceFormatter::formatCad', which is equivalent to the two-element array form — both are recognized as valid callable values.
call_user_func() and call_user_func_array()
Sometimes you have a callable value and a set of arguments computed separately, and you want to invoke the callable dynamically rather than writing $callable(...) directly (which also works, but call_user_func reads more explicitly in some contexts, such as inside generic dispatch code). call_user_func() takes the callable plus each argument individually; call_user_func_array() takes the callable plus a single array of arguments, which is the better choice when the argument count varies at runtime.
call_user_func vs call_user_func_array
<?php
function add(int $a, int $b, int $c = 0): int {
return $a + $b + $c;
}
echo call_user_func('add', 2, 3), "\n";
$args = [5, 10, 15];
echo call_user_func_array('add', $args), "\n";5 30
call_user_func_array shines when the arguments come from somewhere dynamic — form input, a config array, another function's return value — and you do not know at the time you write the code exactly how many there will be.
Combining array callables with call_user_func_array
Dispatching to a method with a dynamic argument list
<?php
class Logger {
public function log(string $level, string $message, string $context = ''): string {
return "[{$level}] {$message} {$context}";
}
}
$logger = new Logger();
$callable = [$logger, 'log'];
$args = ['WARN', 'Disk usage high', '(87%)'];
echo call_user_func_array($callable, $args);[WARN] Disk usage high (87%)
First-class callable syntax (PHP 8.1+)
PHP 8.1 introduced a cleaner way to turn an existing named function or method directly into a Closure, without the string or array indirection: append (...) to the reference instead of calling it. This is called first-class callable syntax.
strlen(...) instead of 'strlen'
<?php
$lengthOf = strlen(...);
echo $lengthOf('Hello'), "\n";
// Works for methods too
class Greeter {
public function greet(string $name): string {
return "Hi, {$name}!";
}
}
$greeter = new Greeter();
$greet = $greeter->greet(...);
echo $greet('Sam');5 Hi, Sam!
The advantage over 'strlen' or [$greeter, 'greet'] is that
strlen(...) and $greeter->greet(...) are checked by IDEs and
static analysis tools the same way an ordinary function call would
be, catching typos in the name or a mismatched argument count before
the code ever runs.
callableaccepts: a function name string, aClosure,[$object, 'method'],[ClassName::class, 'staticMethod'], and'ClassName::staticMethod'.call_user_func($callable, ...$args)invokes with a fixed, individually-listed argument list.call_user_func_array($callable, $argsArray)invokes with a variable-length argument list packed into an array.PHP 8.1's
func(...)first-class callable syntax converts any named function or method reference into a realClosurewith compile-time name checking.