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) сразу видят, что параметр — это «что-то, что будет вызвано».
- Гибкость: одна функция принимает имя функции, метод или замыкание — вызывающий код сам выбирает наиболее удобную форму.
Смотрите также
- Функции обратного вызова в PHP — использование callable с
array_map,usortи другими. - Функции PHP — определение функций, передаваемых как обратные вызовы.
- Статические методы PHP — формы callable для статических методов.
- Типы данных PHP — место
callableсреди типов PHP.