Анонимные функции PHP в хуках WordPress

Анонимные PHP функции, также известные как замыкания (closures) или лямбда-функции, позволяют создавать функции не имеющие определенных имен. В WP они наиболее удобны в качестве значений callback-функций в хуках (фильтрах и событиях). Появились в PHP они начиная с версии 5.3, немного доработаны в 5.4.

Получается, что появились они давно, а если заглянуть в код WordPress плагинов, то там их практически нет. Например, в том же javascript, они используются повсюду. Почему так?

Для начала давайте посмотрим, как выглядит хук с обычной функцией и замыканием:

// 1. хук с обычной функцией
add_filter( 'the_content', 'filter_the_content');
function filter_the_content( $content ){
	// изменяем контент
	return $content;
}

// 2. хук с анонимной функцией
add_filter( 'the_content', function( $content ){
	// изменяем контент
	return $content;
});

У первого способа фактически одно преимущество: так как функция имеет имя, хук при необходимости можно удалить, используя функцию remove_filter() или remove_action(). Поэтому в плагинах и темах анонимные функции редкие гости. А вот если хук создан с помощью замыкания, то надежно удалить его уже нельзя.

Преимущества анонимных функций в WP

  • Короткий синтаксис (удобнее писать).

  • Более чистое глобальное пространство имен и не нужно переживать за конфликты имен функций.

  • Не нужно придумывать названия для callback функций (иногда это отнимает немало времени).

Недостатки анонимных функций в WP

  • Невозможно удалить хук, созданный на базе анонимной функций.

  • Невозможно использовать одну и туже функцию в нескольких хуках - для каждого нужно писать отдельную анонимную функцию. Пример:

    add_filter( 'the_content', 'filter_the_content' );
    add_filter( 'widget_text', 'filter_the_content' );
    
    function filter_the_content( $content ){
    	// Изменяем контент
    	return $content;
    }
    
    // или
    add_filter('the_content', function( $content ){
    	// что-то делаем
    	return $content;
    });
    
    add_filter('widget_text', function( $content ){
    	// что-то делаем
    	return $content;
    });

    Впрочем, этот недостаток неоднозначный, потому что в PHP (с версии 5.3) как и в JS анонимную функцию можно поместить в переменную и затем использовать переменную в качестве коллбек-функции хука:

    $my_callback = function( $content ){
    	// что-то делаем
    	return $content;
    };
    
    add_filter( 'the_content', $my_callback );
    add_filter( 'widget_text', $my_callback );

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

use в анонимных функциях

Еще одна фишка лямбда-функций — это использование переменных из текущей области видимости, с помощью оператора use:

$var = 'Привет мир!';
$func = function() use ( $var ) { echo $var; };
$func(); //> Привет мир!

Переменные передаются как значение, но можно передать и ссылку на переменную, указав &:

$var = 'Привет мир!';
$func = function() use ( & $var ) { $var = $var .' Мы в гости!'; };
$func(); // вызовем
echo $var; //> Привет мир! Мы в гости!

Когда стоит применять анонимные функции в WordPress?

  • Если код не предназначен для широкого использования.

  • Возможность удаления callback функции не нужна и не будет нужна.

  • Не нужна поддержка PHP версий ниже 5.3.

--

Теперь, немного разобравшись что к чему, можно ответить на вопрос, - «Почему в WP не используются анонимные функции?» - Потому что код WP должен быть максимально гибким, а замыкания как раз не про это...

Подробнее про анонимные PHP функции читайте в документации.