W3docs

callable

Подсказка типа callable в PHP — формы обратного вызова, is_callable(), замыкания, __invoke и частые ошибки.

Подсказка типа callable в PHP

Обратный вызов (callback) — это любое значение, которое PHP может вызвать как функцию: имя обычной функции, метод объекта, замыкание и т. д. Подсказка типа callable позволяет объявить, что параметр, свойство или возвращаемое значение должно быть одним из таких вызываемых значений. В сочетании с последующим вызовом ($callback(...)) это основа функций высшего порядка, таких как array_map(), usort() и array_filter().

На этой странице рассматриваются синтаксис, все формы callable, проверка во время выполнения с помощью is_callable() и типичные ошибки.

Синтаксис

Укажите callable перед именем параметра (или в качестве типа свойства/возвращаемого значения), чтобы потребовать вызываемое значение:

<?php

function run(callable $callback) {
  // $callback is guaranteed to be invocable here
  return $callback();
}

Если вызывающий код передаёт невызываемое значение, PHP выбросит TypeError до выполнения тела функции — таким образом, внутри функции можно быть уверены, что $callback() сработает.

Пять форм callable

callable принимает не только имя функции. Каждая строка таблицы ниже представляет отдельное значение, которое PHP признаёт обратным вызовом.

ФормаПример значенияВызывает
Имя функции (string)'strtoupper'именованную функцию
Статический метод (string)'MyClass::myMethod'статический метод
Статический метод (array)['MyClass', 'myMethod']статический метод
Метод экземпляра (array)[$object, 'myMethod']метод объекта $object
Замыкание / стрелочная функцияfunction () { ... }анонимную функцию
Вызываемый объект$obj с __invoke()метод __invoke() объекта

Пример ниже демонстрирует все формы с помощью одного вспомогательного метода run():

<?php

function run(callable $callback): string
{
    return $callback();
}

// 1. A named function passed by string
function greet(): string
{
    return "Hello world!";
}
echo run('greet') . PHP_EOL;

// 2 & 3. Instance method and static method
class Greeter
{
    public function instanceHello(): string
    {
        return "Hello from an instance";
    }

    public static function staticHello(): string
    {
        return "Hello from a static method";
    }
}

$greeter = new Greeter();
echo run([$greeter, 'instanceHello']) . PHP_EOL; // instance method
echo run(['Greeter', 'staticHello']) . PHP_EOL;  // static method
echo run('Greeter::staticHello') . PHP_EOL;      // static method as a string

// 4. A closure (anonymous function)
echo run(function (): string {
    return "Hello from a closure";
}) . PHP_EOL;

// 5. An invokable object (has an __invoke method)
class Loud
{
    public function __invoke(): string
    {
        return "HELLO FROM __INVOKE";
    }
}
echo run(new Loud()) . PHP_EOL;

Результат выполнения:

Hello world!
Hello from an instance
Hello from a static method
Hello from a static method
Hello from a closure
HELLO FROM __INVOKE

Проверка значения с помощью is_callable()

Подсказка типа проверяет входные данные на границе функции, но иногда значение приходит динамически (из конфигурации, пользовательского ввода или реестра) и нужно проверить его до вызова. Используйте is_callable():

<?php

$maybe = 'strtoupper';

if (is_callable($maybe)) {
    echo $maybe('hi'), PHP_EOL; // HI
} else {
    echo "Not callable", PHP_EOL;
}

var_dump(is_callable('strtoupper'));        // bool(true)
var_dump(is_callable('no_such_function'));  // bool(false)
var_dump(is_callable([new DateTime(), 'format'])); // bool(true)

is_callable() возвращает true только если цель существует и доступна — опечатка в имени функции вернёт false вместо ошибки, что делает её идеальной для кода в стиле плагинов.

Синтаксис callable первого класса (PHP 8.1+)

Начиная с PHP 8.1 любую функцию или метод можно преобразовать в Closure с помощью синтаксиса (...). Это типобезопасно, удобно для IDE и позволяет избежать хрупких строк:

<?php

$upper = strtoupper(...);          // a Closure wrapping strtoupper
echo $upper('hello'), PHP_EOL;     // HELLO

$greeter = new DateTime('2020-01-01');
$fmt = $greeter->format(...);      // bound to $greeter
echo $fmt('Y'), PHP_EOL;           // 2020

Поскольку результатом является Closure, он удовлетворяет подсказке типа callable везде, где ожидается обратный вызов.

Частые ошибки

  • Приватные/защищённые методы. Callable вида [$object, 'method'] работает только если метод виден из места его вызова. Вызов приватного метода через строку/массив за пределами его класса завершится ошибкой.
  • callable не может быть типом свойства до PHP 8.2 без оговорок. Использование callable в качестве типа свойства класса не разрешено; вместо этого сохраняйте Closure (или \Closure) или принимайте callable как параметр.
  • Статический вызов без объекта. [$object, 'staticMethod'] работает, но для наглядности лучше использовать ['ClassName', 'staticMethod'] или 'ClassName::staticMethod' для статических целей. Подробнее: статические методы.
  • Строки и объекты. Строковый callable вида 'Greeter::staticHello' работает только для статических методов, но не для методов экземпляра — для вызова методов экземпляра нужна форма массива [$object, 'method'].

Зачем использовать callable?

  • Типовая безопасность: PHP отклоняет недопустимые обратные вызовы на месте вызова с понятным TypeError, а не падает где-то внутри функции.
  • Самодокументируемые сигнатуры: читатели (и инструменты вроде PHPStan или Psalm) сразу видят, что параметр — это «что-то, что будет вызвано».
  • Гибкость: одна функция принимает имя функции, метод или замыкание — вызывающий код сам выбирает наиболее удобную форму.

Смотрите также

Практика

Практика
Что обозначает 'callable' в PHP?
Что обозначает 'callable' в PHP?
Was this page helpful?