Menu

Анонимные функции и замыкания PHP: ключевое слово use

Анонимная функция (замыкание) это функция без имени, сохранённая в переменной: $greet = function ($name) { return "Hi $name"; };. Ключевое слово use, захват по ссылке, callable, синтаксис first-class callable strlen(...) и замыкания внутри классов.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Анонимная функция, её ещё называют замыканием, это функция без имени. Вы пишете 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 () { ... }; это инструкция присваивания, поэтому она заканчивается на ;. Если её пропустить, будет ошибка разбора. Замыканию, переданному прямо как аргумент, своя точка с запятой не нужна.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ