is_callable
Checks whether a value can be called as a function in the current scope.
is_callable(mixed $value, bool $syntax_only = false, string &$callable_name = null): bool- Added in PHP 4.0.6
Parameters
| Parameter | Type | Description |
|---|---|---|
$value | mixed | The value to check. |
$syntax_onlyoptional | bool= false | If true, only verifies that the value has the shape of a callable (a string, a closure, an invokable object, or a two-element array of object/class plus string) without checking that the target actually exists. |
$callable_nameoptional | string= null | Assigned by reference the callable's name, for example "SomeClass::someMethod". |
Return value
booltrue if $value is callable, false otherwise.
Errors
Does not throw, but may trigger class autoloading when $value names a class and $syntax_only is false.
Changelog
- PHP 8.0.0Non-static methods can no longer be checked through a class name: is_callable(['ClassName', 'nonStaticMethod']) and is_callable('ClassName::nonStaticMethod') now return false. Pass an object instance instead.
is_callable() asks whether a value can actually be invoked right now. It accepts every callable form: a function-name string, 'Class::staticMethod', an [$object, 'method'] or ['Class', 'staticMethod'] array, a Closure, and any object whose class defines __invoke().
With the default $syntax_only = false it performs a real lookup — the function or method must exist and be reachable from the calling scope, which means a private method returns false when checked from outside the class. Set $syntax_only to true to skip the lookup and only validate the shape; that avoids autoloading a class you do not want loaded yet.
Two traps worth knowing
A class implementing __call() makes is_callable([$obj, 'anything']) return true for every method name, since the magic method could handle it. If you need to know whether a real method is declared, use method_exists() instead — or both, since they answer different questions.
Since PHP 8.0, checking a non-static method through a class name returns false; you must pass an instance.
When to reach for it
Validate a user-supplied callback before storing it in an event dispatcher, plugin registry or middleware pipeline, so the failure surfaces at registration rather than deep inside a dispatch loop.
Example
When to use it
- Validating a callback passed into an event dispatcher or plugin registry before it is stored
- Checking that an optional hook exists on an object before invoking it in a middleware pipeline
- Using $syntax_only = true to sanity-check a 'Class::method' config string without autoloading the class
Frequently asked questions
What is the difference between is_callable() and function_exists()?
function_exists() only handles plain function-name strings, while is_callable() also accepts closures, invokable objects and [object, 'method'] arrays, and checks visibility from the calling scope. Use is_callable() for anything you intend to invoke as a callback.
Why does is_callable(['MyClass', 'myMethod']) return false?
Because since PHP 8.0 a non-static method can no longer be checked through its class name. Pass an instance instead: is_callable([new MyClass(), 'myMethod']).
Does is_callable() autoload classes?
Yes, when you pass a class-name based callable and leave $syntax_only as false. Set $syntax_only to true to validate the shape without triggering the autoloader.
More examples
syntax_only and the callable name
The static method resolves and $name comes back as DateTime::createFromFormat. The missing class fails the real lookup but passes the syntax-only check, which still fills in the name — useful for validating config strings before the class is loaded.
<?php
var_dump(is_callable(['DateTime', 'createFromFormat'], false, $name));
echo $name, "\n";
var_dump(is_callable(['NoSuchClass', 'nope'], false, $n2));
var_dump(is_callable(['NoSuchClass', 'nope'], true, $n3));
echo $n3, "\n";__call() makes everything callable
is_callable() says true because __call() would indeed handle the invocation, while method_exists() correctly says the method is not declared. Both answers are right — they just answer different questions.
<?php
class Proxy {
public function __call(string $name, array $args): string {
return "forwarded: $name";
}
}
$p = new Proxy();
var_dump(is_callable([$p, 'anythingAtAll']));
var_dump(method_exists($p, 'anythingAtAll'));
echo $p->anythingAtAll(), "\n";Registering validated handlers
The invalid handler is caught at registration time with a clear message instead of causing a fatal Error later during dispatch. The three surviving callables — two named functions and one closure — all run through the same call site.
<?php
$handlers = ['strtoupper', 'no_such_function', fn($s) => "[$s]", 'trim'];
$valid = [];
foreach ($handlers as $h) {
if (is_callable($h)) {
$valid[] = $h;
} else {
echo 'rejected: ', get_debug_type($h), ' ', var_export($h, true), "\n";
}
}
foreach ($valid as $fn) {
echo $fn(' php '), "\n";
}
Discussion