Анонимная функция, её ещё называют замыканием, это функция без имени. Вы пишете function ($param) { ... } там, где ожидается значение: присваиваете переменной, передаёте в другую функцию или возвращаете. Она может нести с собой переменные окружающего кода через use ($var).
Каждая анонимная функция это объект встроенного класса Closure, поэтому её можно хранить, передавать и вызывать позже через $greet(...).
Ключевое слово use захватывает по значению
Замыкание само по себе не видит внешние переменные. use ($x) копирует значение $x в замыкание в момент создания замыкания, а не в момент его выполнения:
use по ссылке: &$var
use (&$x) даёт замыканию саму переменную, а не копию. Изменения внутри замыкания видны снаружи, а изменения снаружи видны внутри. Так колбэк прибавляет к сумме или ведёт счётчик.
Каждый вызов makeCounter() создаёт новую $count, и возвращённое замыкание сохраняет её живой после того, как функция завершилась. Именно это и означает слово "замыкание": функция замыкает в себе нужные ей переменные.
Замыкание как колбэк
Функции вроде array_map(), array_filter(), usort() и array_walk() принимают функцию аргументом. Замыкание позволяет написать её прямо на месте, со столькими инструкциями, сколько нужно:
Когда тело это одно выражение, стрелочная функция вроде fn($p) => $p['price'] короче и не требует use.
Callable: имена функций, методы и strlen(...)
Параметр с типом callable принимает не только замыкания. Подходят строка с именем функции, массив с объектом и именем метода и массив с именем класса и именем статического метода. Начиная с PHP 8.1 синтаксис first-class callable strlen(...) превращает любой из них прямо в Closure.
Форма (...) проверяется при выполнении строки: опечатка сразу выбрасывает Error. Строка вроде 'strtoupr' остаётся просто строкой, пока кто-нибудь не попытается её вызвать.
Замыкания внутри класса: $this и static
У замыкания, созданного внутри метода, $this привязывается автоматически, поэтому оно может использовать свойства объекта. Помечайте его static function, когда $this не нужен: это ещё и не даёт ему удерживать объект в памяти.
Забытый use
Самая частая ошибка с замыканиями: использовать внешнюю переменную, не перечислив её в use. Внутри замыкания такой переменной не существует:
$minAge = 18;
$adults = array_filter($people, function ($p) {
return $p['age'] >= $minAge; // $minAge is not in use (...)
});
PHP prints: Warning: Undefined variable $minAge
$minAge внутри равна null, любой возраст при сравнении >= null даёт true, и через фильтр проходит каждый. На сервере, который скрывает предупреждения, ничто вам об этом не скажет. Добавьте переменную в use:
Часто задаваемые вопросы
Что такое замыкание в PHP?
Функция без имени, созданная через function (...) { ... } и сохранённая в переменной или переданная как аргумент. PHP представляет её объектом класса Closure. Она может нести с собой переменные из той области видимости, где создана, перечисленные в use (...).
Что делает ключевое слово use в замыкании PHP?
use ($x) копирует внешнюю переменную $x в замыкание в момент его создания. Последующие изменения $x снаружи замыкание не видит. Пишите use (&$x), чтобы разделять переменную, и тогда изменения работают в обе стороны.
Что такое callable в PHP?
Всё, что PHP может вызвать: замыкание, имя функции строкой ('strtoupper'), массив [$object, 'method'] или [ClassName::class, 'staticMethod'] либо объект с __invoke(). Используйте тип callable, чтобы принимать любой из них, и is_callable() для проверки.
Что означает strlen(...) в PHP?
Это синтаксис first-class callable из PHP 8.1: strlen(...) создаёт Closure из функции, не вызывая её. Он работает и для методов, $obj->method(...), и для статических методов, Foo::bar(...), и проверяется в момент выполнения строки, в отличие от имени в строке.
Нужна ли точка с запятой после анонимной функции?
Да, когда вы её присваиваете: $f = function () { ... }; это инструкция присваивания, поэтому она заканчивается на ;. Если её пропустить, будет ошибка разбора. Замыканию, переданному прямо как аргумент, своя точка с запятой не нужна.