Types7 min readExamples run on PHP 8.5.10

is_callable()

Learn how PHP 8.4 is_callable() checks functions, closures, array callables and invokable objects, and how syntax_only and callable_name change the result.

Signature

is_callable(mixed $value, bool $syntax_only = false, string &$callable_name = null): bool
Available since PHP 4.0.67.48.08.18.28.38.48.5All versions →

Purpose

is_callable() answers one question: could this value be invoked as a callback from the current scope? It is most useful before you store or run a callback that came from configuration, a plugin list or a function argument. Instead of letting call_user_func() fail later, you can check early and reject the value with a clear message.

The function accepts any value. Strings, closures, objects and arrays can all be callable, depending on their shape and on what exists when the check runs.

Signature

Parameters and defaults

  • $value is the value to test. It has no default.
  • $syntax_only defaults to false. In that mode PHP checks that the callable really exists and can be reached from the current scope. When set to true, PHP only checks the structure. A string passes, an invokable object or Closure passes, and an array passes if it has two entries: an object or string first, and a string second.
  • $callable_name is an optional by-reference output. PHP fills it with a readable name such as SomeClass::someMethod. It is a label for display or logging, not proof that a static method exists.

Return value and failure cases

The return type is bool. You get true when the value is callable and false otherwise. A bad value does not throw an exception, so an unknown function name, a wrong array shape or an inaccessible method simply gives false.

The result depends on the calling scope. A private method can be callable from inside its own class but not from outside. The function may also trigger autoloading when you pass a class name.

Example 1: functions, closures and plain strings

A string is callable when it names an existing function. Closures are always callable. Other strings are not.

Example
<?php

function greet(string $name): string
{
    return "Hello, $name";
}

$checks = [
    'named function' => is_callable('greet'),
    'built-in function' => is_callable('strtoupper'),
    'missing function' => is_callable('no_such_function_here'),
    'closure' => is_callable(fn(int $n): int => $n * 2),
    'plain string' => is_callable('not a function'),
];

echo json_encode($checks, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"named function":true,"built-in function":true,"missing function":false,"closure":true,"plain string":false}

Example 2: methods, visibility and invokable objects

An array callable is [$objectOrClass, 'method']. The method must exist and be visible from where you call is_callable(). A non-static method named through a class string is not callable, which matches the manual's ['Foo', 'foo'] example. An object with a visible __invoke() method is callable itself.

Example
<?php

class Greeter
{
    public function hello(): string
    {
        return 'hello';
    }

    public static function make(): string
    {
        return 'made';
    }

    private function secret(): string
    {
        return 'secret';
    }

    public function __invoke(): string
    {
        return 'invoked';
    }
}

$greeter = new Greeter();

$checks = [
    'instance method' => is_callable([$greeter, 'hello']),
    'static method string' => is_callable('Greeter::make'),
    'static method array' => is_callable(['Greeter', 'make']),
    'private from outside' => is_callable([$greeter, 'secret']),
    'invokable object' => is_callable($greeter),
    'missing method' => is_callable([$greeter, 'missing']),
    'non-static via class name' => is_callable(['Greeter', 'hello']),
];

echo json_encode($checks, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"instance method":true,"static method string":true,"static method array":true,"private from outside":false,"invokable object":true,"missing method":false,"non-static via class name":false}

Example 3: syntax_only, __call() and callable_name

With syntax_only set to true, a string that names no function still passes, because the shape is plausible. An array with the wrong types fails. If an object implements __call(), any method name on that object counts as callable.

Example
<?php

class Router
{
    public function __call(string $name, array $arguments): string
    {
        return $name;
    }
}

$router = new Router();

$actual = is_callable('missing_function_name');
$syntax = is_callable('missing_function_name', true, $nameForString);
$magic = is_callable([$router, 'anything'], false, $nameForArray);
$badShape = is_callable([1, 2], true);

echo json_encode([
    'actual' => $actual,
    'syntaxOnly' => $syntax,
    'magicCall' => $magic,
    'badShape' => $badShape,
    'stringName' => $nameForString,
    'arrayName' => $nameForArray,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"actual":false,"syntaxOnly":true,"magicCall":true,"badShape":false,"stringName":"missing_function_name","arrayName":"Router::anything"}

Edge cases

  • A class name string is callable only when the class implements __callStatic(), as the manual notes.
  • Constructors are not static methods. is_callable(['Foo', '__construct']) is false, while is_callable([$foo, '__construct']) is true for an existing object. Do not use the function to decide whether a class can be instantiated.
  • Because of __call(), a true result for an object does not prove that a real method with that name exists.
  • Autoloading can run when you check a class name, so the check may have side effects in an application with autoloaders.

Common mistakes

  1. Using syntax_only as an existence check. It only validates shape. Leave it false when you need to know that the call can succeed.
  2. Trusting callable_name. The name SomeClass::someMethod is a label. It does not make the method a static method.
  3. Confusing it with function_exists() or method_exists(). Those functions check definitions. is_callable() also considers visibility, magic methods and invokable objects.
  4. Passing 'Class::method' for an instance method. In PHP 8 a non-static method cannot be called statically, so the check fails. Pass [$object, 'method'] instead.
  5. Ignoring scope. A private or protected method may be callable in one place and not in another.
  • call_user_func() calls the callback given as its first argument.
  • function_exists() reports whether a function has been defined.
  • method_exists() checks whether a class or object has a method.

Recap

Use is_callable() to validate callbacks before running them. Keep syntax_only off for real reachability checks, read callable_name as a display label, and remember that __invoke(), __call(), __callStatic() and the calling scope can all change the answer.

Tested examples

Functions, closures and plain strings
<?php

function greet(string $name): string
{
    return "Hello, $name";
}

$checks = [
    'named function' => is_callable('greet'),
    'built-in function' => is_callable('strtoupper'),
    'missing function' => is_callable('no_such_function_here'),
    'closure' => is_callable(fn(int $n): int => $n * 2),
    'plain string' => is_callable('not a function'),
];

echo json_encode($checks, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"named function":true,"built-in function":true,"missing function":false,"closure":true,"plain string":false}
Methods, visibility and invokable objects
<?php

class Greeter
{
    public function hello(): string
    {
        return 'hello';
    }

    public static function make(): string
    {
        return 'made';
    }

    private function secret(): string
    {
        return 'secret';
    }

    public function __invoke(): string
    {
        return 'invoked';
    }
}

$greeter = new Greeter();

$checks = [
    'instance method' => is_callable([$greeter, 'hello']),
    'static method string' => is_callable('Greeter::make'),
    'static method array' => is_callable(['Greeter', 'make']),
    'private from outside' => is_callable([$greeter, 'secret']),
    'invokable object' => is_callable($greeter),
    'missing method' => is_callable([$greeter, 'missing']),
    'non-static via class name' => is_callable(['Greeter', 'hello']),
];

echo json_encode($checks, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"instance method":true,"static method string":true,"static method array":true,"private from outside":false,"invokable object":true,"missing method":false,"non-static via class name":false}
syntax_only, __call() and callable_name
<?php

class Router
{
    public function __call(string $name, array $arguments): string
    {
        return $name;
    }
}

$router = new Router();

$actual = is_callable('missing_function_name');
$syntax = is_callable('missing_function_name', true, $nameForString);
$magic = is_callable([$router, 'anything'], false, $nameForArray);
$badShape = is_callable([1, 2], true);

echo json_encode([
    'actual' => $actual,
    'syntaxOnly' => $syntax,
    'magicCall' => $magic,
    'badShape' => $badShape,
    'stringName' => $nameForString,
    'arrayName' => $nameForArray,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"actual":false,"syntaxOnly":true,"magicCall":true,"badShape":false,"stringName":"missing_function_name","arrayName":"Router::anything"}