Замыкания в PHP. Что такое анонимная функция и как добавить её в переменную?

замыкания в php. что такое
   анонимная функция и как добавить её  в переменную?

Что из себя представляют замыкания?

В прошлых статьях мы говорили, что при объявлении функции нужно указывать её имя. Это необходимо для дальнейших вызовов в любом месте программы. Такое поведение заложено в природе функций. Они призваны бороться с повторяемостью кода при написании PHP-скриптов.

Каждая именованная функция занимает место в глобальном пространстве, и существует до завершения выполнения скрипта. Бывают ситуации, когда функцию нужно использовать единожды и добавление её имени в глобальное пространство не желательно. Для этих целей PHP позволяет создавать анонимные функции, или как их ещё называют - замыкания.

Важно
Замыкания, при создании, должны быть помещены в переменную, в элемент массива или переданы в качестве параметра при вызове другой функции. Если их не сохранить где-нибудь для дальнейшего использования, то и вызвать на выполнение будет невозможно.

Создание и использование замыканий

Правила создания анонимных функций:

  1. Выражение должно начинаться со слова function. Это обусловлено требованиями синтаксиса PHP. Если вы забудете указать его, то программный код завершится с ошибкой.
  2. Сразу за словом function (без указания имени функции), внутри круглых скобок описываются принимаемые параметры.
  3. За закрывающей скобкой описания параметров может быть расположено необязательное ключевое слово use. Оно определяет наследования замыкания (о наследованиях далее в статье).
  4. Если указано ключевое слово use, то после него должны располагаться круглые скобки. В них через запятую указываются имена наследуемых переменных, доступных в родительской области видимости.
  5. После описания параметров или наследований, располагаются фигурные скобки, между которыми задается программный код, требующий выполнения.
//Помещаем анонимную функцию внутрь обычной переменной
$showName = function($name) {
    echo 'Мое имя: '. $name .'<br>';
};

//Осуществляем несколько вызовов через переменную
$showName('Олег'); //Результат: Мое имя: Олег
$showName('Андрей'); //Результат: Мое имя: Андрей

Как видно из примера, приведенного выше, анонимная функция может быть помещена в переменную. Для её вызова необходимо указать имя переменной и круглые скобки с передачей нужных параметров. В общем представлении это выражение может выглядеть как «$имя_переменной($первый_параметр, $второй_параметр);».

В PHP существует ряд встроенных функций, которые могут принимать замыкания в качестве параметров. Одной из таких функций является array_walk(), в первый параметр которой можно передать массив, а во второй замыкание. В процессе выполнения array_walk(), будет осуществлен обход всех элементов массива. Для каждого из них будет выполнено замыкание, в первый параметр которого будут передаваться ключи, а во второй значения элементов.

//Создаем массив для перебора через array_walk
$colorsToFlower = [
    'Красный' => 'Роза',
    'Желтый' => 'Тюльпан',
    'Синий' => 'Василек'
];

//Перебираем массив с помощью функции array_walk
//и выводим специально сформированную строку
array_walk($colorsToFlower, function($color, $flower){
    echo "Цвет - $color : Растение - $flower<br>";
});

//То же самое, но только с использованием цикла
foreach($colorsToFlower as $color => $flower) {
    echo "Цвет - $color : Растение - $flower<br>";
}

/*
* В обоих случаях, результат:
* Цвет - Красный : Растение - Роза
* Цвет - Желтый : Растение - Тюльпан
* Цвет - Синий : Растение - Василек
*/

Заметка
Если анонимная функция была помещена в переменную, то удаление этой переменной позволит высвободить оперативную память. В PHP действует механизм «сборки мусора», который самостоятельно занимается удалением неиспользуемых переменных, но все же вы можете контролировать этот процесс вручную.

Наследования из родительской области видимости

Если при создании замыкания было использовано ключевое слово use, то сразу за ним, в круглых скобках, можно указать имена переменных из родительской области видимости. Эти переменные будут доступны внутри замыкания при его вызове.

//Переменные из родительского окружения
$operationSystem = 'Windows';
$timeToShutdown = 1000;

//Определяем анонимную функцию, наследующую значения
//переменных из родительской области видимости
$systemInfo = function() use ($operationSystem, $timeToShutdown){
    echo "Вы работаете на ОС: $operationSystem<br>";
    echo "Время до выключения системы: $timeToShutdown минут";
};

//Вызываем анонимную функцию, хранящуюся в переменной
$systemInfo();
/*
* Результат:
* Вы работаете на ОС: Windows
* Время до выключения системы: 1000 минут
*/

Обратите внимание, наследования передаются как копии тех значений, которые существовали в указанных переменных на момент создания анонимной функции. Если в промежутке, между созданием анонимной функции и её вызовом, значения унаследованных переменных были изменены, то функция ничего об этом не узнает. Исправить такое поведение можно с помощью ссылок.

//Переменные из родительского окружения
$color = 'Желтый';
$car = 'Пежо';

//Определяем анонимную функцию обычным
// наследованием и использованием ссылки
$carInfo = function() use ($color, &$car){
    echo "Цвет автомобиля: $color<br>";
    echo "Марка автомобиля: $car";
};

//Изменяем данные унаследованных переменных
$color = 'Красный';
$car = 'Мустанг';

//Видим, что цвет автомобиля остался прежний,
//а марка изменилась, так как передана по ссылке
$carInfo();
/*
* Результат:
* Цвет автомобиля: Желтый
* Марка автомобиля: Мустанг
*/

Последние публикации