Функции обратного вызова (callback) и замыкания
10 июля 2018
Для реализации событийной модели и создания обработчиков (callback-функций) удобно использовать анонимные функции (также известные как замыкания). При передаче в функцию аргумента-замыкания этот параметр автоматически преобразуются техникой языка в объект класса Closure, который принадлежит к псевдотипу данных callable. Данный псевдотип обозначает значение, которое может быть вызвано как функция. К таким значениям относится строка с названием пользовательской функции, массив с парой значений (имя класса и название метода), анонимная функция, объект с реализованным методом __invoke. Проверка принадлежности аргумента к псевдотипу callable выполняется с помощью функции is_callable
Документация по анонимным функциям https://www.php.net/manual/ru/functions.anonymous.php
Документация по is_callable https://www.php.net/manual/ru/function.is-callable.php
Пример кода с функцией добавления пользователя. Если добавление проходит успешно, то выполняется функция обратного вызова (в этом частном примере указана анонимная функция):
Например, следующий код ничего не выведет, т.к переменные $m_hello и $m_user не доступны внутри области видимости функции
Что бы переменные из родительской области видимости были видны внутри замыкания, нужно использовать конструкцию use. Но надо учитывать, что значения переменных будут взяты по состоянию на момент определения функции, а не её вызова. Это значит, что если значение переменной изменится после определения функции, то внутри функции будет использовано значение переменной, которые было на момент определения замыкания
Документация по анонимным функциям https://www.php.net/manual/ru/functions.anonymous.php
Документация по is_callable https://www.php.net/manual/ru/function.is-callable.php
Пример кода с функцией добавления пользователя. Если добавление проходит успешно, то выполняется функция обратного вызова (в этом частном примере указана анонимная функция):
// Добавляет пользователя в систему
// @param array $fields - массив с информацией о пользователе
// @params callable $event - событие, срабатывающий в случае успешного добавления пользователя
// @return bool - true, если пользователь успешно добвлен и false в противном случае
function add_user(array $fields, callable $event=NULL)
{
// добавление пользователя: начало
// ...
// добавление пользователя: конец
//Если установлена функция обратного вызова, то вызываем её
if(is_callable($event)) $event();
return true;
}
add_user(array(
'NAME' => 'Владимир',
'GENDER' => 'm',
'COUNTRY' => 'Россия',
), function(){
echo 'Вы успешно зарегистрированы';
});
Конструкция use
Иногда нужно использовать переменные, объявленные за пределами определения функции, в родительской области видимости.Например, следующий код ничего не выведет, т.к переменные $m_hello и $m_user не доступны внутри области видимости функции
$m_hello = 'Здравствуйте, ';
$m_user = 'пользователь';
$a = function()
{
echo $m_hello.$m_user;
};
/*
Функция ничего не выведет, т.к переменные $m_hello и $m_user
в теле функции не заданы, а за пределами тела их не видно
*/
$a();
Что бы переменные из родительской области видимости были видны внутри замыкания, нужно использовать конструкцию use. Но надо учитывать, что значения переменных будут взяты по состоянию на момент определения функции, а не её вызова. Это значит, что если значение переменной изменится после определения функции, то внутри функции будет использовано значение переменной, которые было на момент определения замыкания
$m_hello = 'Здравствуйте, ';
$m_user = 'пользователь';
$a = function() use ($m_hello, $m_user)
{
echo $m_hello.$m_user;
};
//Изменяем одну переменную
$m_hello = 'Hello, ';
$a(); /* Выведет 'Здравствуйте, пользователь' */