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

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

· PHP · 4 мин чтения
AnyComment - Современный виджет комментариев для WordPress

В этой записи, я расскажу про анонимные функции в 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)

Объяснение

PHP объяснение callback

Я создал новый класс 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() — выводи содержимого в читабельном формате