PHP: анонимные функции. Где и как использовать?

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

Обычная функция vs. анонимная функция

Обычная функция выглядит примерно так:

  1. function printName() {
  2. return ‘alex’;
  3. }

Вызывается следующим образом:

  1. echo printName();

Анонимная функция (Closure), в PHP дает возможность создавать функцию без имени (например, без printName() как в примере выше). Они части используются в роли callback.

Анонимные функции всегда возвращают Closure. Особо не нагружайте себя почему, чуть ниже, в этом посту я распишу почему так.

Давайте рассмотрим следующий пример анонимной функции:

  1. $string = ‘Привет мир!’;
  2. $func = function() use (&$string) {
  3. echo $string;
  4. };
  5. $func();

У нас есть переменная $string и $func. Где $string — это обычная переменная со строкой, где $func — это переменная, которая хранит результат анонимную функцию.

Этой частью кода:

  1. $func = function() use (&$string)

Вы обозначаете, что хотите использовать анонимную функцию и внутри внутри нужно использовать переменную $string.

Что мы и делаем:

  1. echo $string;

В самом конце вызываем анонимную функцию добавляя к переменной «()», тем самым делая из нее функцию:

  1. $func();

Анонимная функция в переменной

В примере выше, где проводилось сравнение, анонимная функция использовалась в виде переменной.

Чтобы не мешать все в кучу, давайте создадим новый пример:

  1. <?php
  2. $namePrinter = function($name) {
  3. echo sprintf(«Куку %sn», $name);
  4. };
  5. $namePrinter(‘Вася’);
  6. $namePrinter(‘Петр’);
  7. $namePrinter(‘Саша’);

Результат:

  1. Куку Вася
  2. Куку Петр
  3. Куку Саша

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

Больше:  Стоят ли тестовые рекламные кампании затраченных денег и усилий?

Анонимная функция как callback

Давайте рассмотрим следующий пример callback функции:

  1. $names = [‘alex’, ‘petr’];
  2. function upperCase($name) {
  3. return «Хай « . ucfirst( $name );
  4. }
  5. print_r ( array_map( upperCase, $names ) );

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

В сам конце мы используем array_map(). Первый аргумент — это функция обозначенная выше, второй — это имена с первой строчки.

array_map() проходится по массиву с вашим обозначенной callback функцией.

Результат вывода:

  1. Array ( [] => Хай Alex [1] => Хай Petr )

Надо бы переписывать пример выше, так как в реальной жизни вы не должны писать мини функцию в таком случае, иначе размер вашего файла будет расти и расти, а это не есть хорошо 🙂

Смотрите новый вариант, который состоит всего из 5 строк:

  1. $names = [‘alex’, ‘petr’];
  2. print_r ( array_map( function($name) {
  3. return «Хай « . ucfirst( $name );
  4. }, $names ) );

Результат точно такой же как и в примере выше.

Создание Closure с анонимной функцией

Давайте рассмотрим такой приме:

  1. <?php
  2. class Test {
  3. public static function doSomething($num, $closure = null) {
  4. if( !$closure instanceof Closure ) {
  5. return $num;
  6. }
  7. if( ($value = call_user_func($closure, $num)) && is_int($value) ) {
  8. return $value * $num;
  9. }
  10. return $num;
  11. }
  12. }
  13. $t = new Test();
  14. var_dump($t>doSomething(10, function($passedNum) {
  15. return $passedNum * 5;
  16. }));

Вывод:

  1. int(500)

Объяснение

Я создал новый класс Test, который включает в себя один метод doSomething() с двуми передаваемым параметрами: $num$closure. Второй параметр не обязательный.

Логика doSomething() следующая:

  • если $closure не является Closure, тогда мы возвращаем $num
  • если $closure является Closure, тогда мы вызывает ее используя call_user_func() и как параметр функции вызывает саму $closure и передаем обратно $num, чтобы тот, кто используем метод, мог воспользоваться числом (если потребуется). Далее проверяем, что вернулась цифра (потому что это то, что я ожидаю), если все ок, тогда умножаем $num на $value, которое вернулось из $closure
  • в ином случае возвращаем $num