В этой записи, я расскажу про анонимные функции в PHP, как и где их использовать. Покажу множество разных примеров использования и дам общие рекомендации по использованию.
Обычная функция vs. анонимная функция
Обычная функция выглядит примерно так:
function printName() { return 'alex'; }
Вызывается следующим образом:
echo printName();
Анонимная функция (Closure), в PHP дает возможность создавать функцию без имени (например, без printName()
как в примере выше). Они части используются в роли callback.
Анонимные функции всегда возвращают Closure. Особо не нагружайте себя почему, чуть ниже, в этом посту я распишу почему так.
Давайте рассмотрим следующий пример анонимной функции:
$string = 'Привет мир!'; $func = function() use (&$string) { echo $string; }; $func();
У нас есть переменная $string
и $func
. Где $string
— это обычная переменная со строкой, где $func
— это переменная, которая хранит результат анонимную функцию.
Этой частью кода:
$func = function() use (&$string)
Вы обозначаете, что хотите использовать анонимную функцию и внутри внутри нужно использовать переменную $string
.
Что мы и делаем:
echo $string;
В самом конце вызываем анонимную функцию добавляя к переменной «()», тем самым делая из нее функцию:
$func();
Анонимная функция в переменной
В примере выше, где проводилось сравнение, анонимная функция использовалась в виде переменной.
Чтобы не мешать все в кучу, давайте создадим новый пример:
<?php $namePrinter = function($name) { echo sprintf("Куку %s\n", $name); }; $namePrinter('Вася'); $namePrinter('Петр'); $namePrinter('Саша');
Результат:
Куку Вася Куку Петр Куку Саша
В этом примере мы используем $namePrinter()
для вызова анонимной функции, но альтернативно вы могли бы создать функцию с названием namePrinter()
и вызывать точно в таком же порядке.
Анонимная функция как callback
Давайте рассмотрим следующий пример callback функции:
$names = ['alex', 'petr']; function upperCase($name) { return "Хай " . ucfirst( $name ); } print_r ( array_map( upperCase, $names ) );
В этом примере, обозначили массив с двумя имена в нижнем регистре. На третье строчке, у нас функция, которые принимает значение параметр в виде имени, переводит первую букву имени в верхний регистр и возвращает результат.
В сам конце мы используем array_map()
. Первый аргумент — это функция обозначенная выше, второй — это имена с первой строчки.
array_map() проходится по массиву с вашим обозначенной callback функцией.
Результат вывода:
Array ( [0] => Хай Alex [1] => Хай Petr )
Надо бы переписывать пример выше, так как в реальной жизни вы не должны писать мини функцию в таком случае, иначе размер вашего файла будет расти и расти, а это не есть хорошо :)
Смотрите новый вариант, который состоит всего из 5 строк:
$names = ['alex', 'petr']; print_r ( array_map( function($name) { return "Хай " . ucfirst( $name ); }, $names ) );
Результат точно такой же как и в примере выше.
Создание Closure с анонимной функцией
Давайте рассмотрим такой приме:
<?php class Test { public static function doSomething($num, $closure = null) { if( !$closure instanceof \Closure ) { return $num; } if( ($value = call_user_func($closure, $num)) && is_int($value) ) { return $value * $num; } return $num; } } $t = new Test(); var_dump($t->doSomething(10, function($passedNum) { return $passedNum * 5; }));
Вывод:
int(500)
Объяснение
Я создал новый класс Test
, который включает в себя один метод doSomething()
с двуми передаваемым параметрами: $num
, $closure
. Второй параметр не обязательный.
Логика doSomething()
следующая:
- если
$closure
не являетсяClosure
, тогда мы возвращаем$num
- если
$closure
являетсяClosure
, тогда мы вызывает ее используяcall_user_func()
и как параметр функции вызывает саму$closure
и передаем обратно$num
, чтобы тот, кто используем метод, мог воспользоваться числом (если потребуется). Далее проверяем, что вернулась цифра (потому что это то, что я ожидаю), если все ок, тогда умножаем$num
на$value
, которое вернулось из$closure
- в ином случае возвращаем
$num
Источники
- call_user_func() — вызывать передаваемую callback функцию с параметрами (если требуется)
- Closure — формат анонимной функции
- ucfirst() — перевод первой буквы в верхний регистр
- sprintf() — формат строк
- print_r() — выводи содержимого в читабельном формате