В чем разница между фильтрами и хуками действий?
В последнее время я более подробно изучаю API плагинов, и меня интересует какие реальные различия существуют между хуками действий (action hooks) и фильтрами (filter hooks). Оба они являются событиями, которые получают данные в качестве параметра, и, похоже, они оба могут выполнять одни и те же функции.
Очевидно, я понимаю, что действия вызываются при выполнении определенных действий, а фильтры вызываются при манипуляции данными, но кажется, что это просто семантическое различие в названиях.
Помимо семантики и их предназначения, какие реальные различия существуют между ними?

Привет @Sruly:
Ты практически сам ответил на свой вопрос, но я немного разверну ответ.
Хуки действий (Action Hooks)
Хуки действий предназначены для случаев, когда WordPress или какой-то плагин/тема дают вам возможность вставить свой код в определённой точке и выполнить одно или несколько из следующих действий:
- Использовать
echo
для вставки HTML или другого контента в буфер вывода, - Изменять глобальные переменные (одну или несколько), и/или
- Модифицировать параметры, переданные в функцию хука (при условии, что хук был вызван через
do_action_ref_array()
, а неdo_action()
, так как последний не поддерживает передачу переменных по ссылке).
Хуки фильтров (Filter Hooks)
Хуки фильтров ведут себя очень похоже на хуки действий, но их основное назначение — получить значение и потенциально вернуть его модифицированную версию. Хук фильтра также может использоваться как хук действия — например, для изменения глобальной переменной или генерации HTML, если это требуется при вызове хука. Очень важный момент, который отличает хуки фильтров от хуков действий: функция, использующая хук фильтра, обязана вернуть (модифицированную версию) первого переданного параметра. Частая ошибка новичков — забыть вернуть это значение!
Использование дополнительных параметров для контекста в хуках фильтров
К слову, мне казалось, что хуки фильтров в ранних версиях WordPress были ограничены, так как получали только один параметр — значение для модификации, но без второго или третьего параметра, который мог бы дать контекст. Однако в последнее время команда WordPress начала добавлять дополнительные параметры в хуки фильтров, что очень радует. Хороший пример — хук posts_where
: раньше он принимал только один параметр (SQL-условие "WHERE" текущего запроса), но теперь он принимает и условие WHERE, и ссылку на текущий экземпляр класса WP_Query
, который вызывает хук.
Так в чём же реальная разница?
По сути, хуки фильтров — это расширенная версия хуков действий. Они могут делать всё то же самое и даже немного больше, хотя разработчик не обязан возвращать значение в хуке действий, как это требуется в хуке фильтров.
Передача намерений и указание цели
Но, вероятно, важно не это. Важно то, что, выбирая между хуком действия и хуком фильтра, разработчик передаёт своё намерение и тем самым даёт подсказку разработчику темы или плагина, который будет использовать этот хук. По сути, он говорит либо "Я вызову тебя, делай что нужно", ЛИБО "Я передам тебе это значение для модификации, но не забудь вернуть его обратно".
Таким образом, я считаю, что ключевая ценность различия между типами хуков заключается в подсказке, которую они дают. По крайней мере, так мне кажется.
Надеюсь, это поможет!

Мне кажется, можно было бы использовать только фильтры для всего, так как возврат переменной в PHP необязателен. Кто-нибудь знает, почему разработчики WordPress выбрали разделение на два разных термина? Это чисто семантические причины? Технически я не вижу в этом необходимости...

@TheStoryCoder "Это чисто семантические причины?" Похоже, что именно это мой ответ и объяснил пять (5) лет назад...?

Если посмотреть исходный код основной функции add_action()
, то это просто обёртка для функции add_filter()
...
А если изучить функцию do_action()
, то она очень похожа на основную функцию apply_filters()
, с одним ключевым отличием: она не возвращает значение.
Что это значит? Действия (actions) похожи на фильтры (filters), за исключением того, что действие не возвращает значение, поэтому вы не можете модифицировать данные. Это показывает, что механизм действий в WordPress был создан просто копированием механизма фильтров, но без возврата значения. По сути, всё что вы можете сделать с действием — это просто выполнить функцию без модификации какого-либо значения.

Простыми словами.
Действия (Actions) — это PHP-функции, которые выполняют вывод.
Фильтры (Filters) — это PHP-функции, которые возвращают вывод.
Обновлено: Мы можем расширить любой плагин, который использует действия и фильтры, без изменения его кода. Добавляя фильтры и действия в нашей собственной теме или плагине.
Как использовать?
Действия (Actions):
Проверьте простые примеры ниже в файле functions.php
вашей темы.
- Пример первый: (Простой пример на PHP)
function test() { echo "Вывод"; } test();
Вывод программы выше:
Вывод
[ПРИМЕЧАНИЕ: Здесь test()
просто вызывает функцию и выполняет callback-функцию 'test'.]
- Пример второй: (Простое использование действия)
function test1() { echo "Вывод"; } add_action( 'test', 'test1' ); do_action( 'test' );
Вывод программы выше:
Вывод
[ПРИМЕЧАНИЕ: Здесь do_action('test')
работает как вызов функции и выполняет callback-функцию 'test1'.]
- Пример третий: (Другое использование действий)
function test2() { echo "Тест 2"; } add_action( 'test', 'test2', 1 ); function test1() { echo "Тест 1"; } add_action( 'test', 'test1', 2 ); do_action( 'test' );
Вывод программы выше:
Тест 2Тест 1
[ПРИМЕЧАНИЕ: Здесь do_action('test')
работает как вызов функции и выполняет callback-функции в соответствии с их приоритетами.
Callback-функция 'test1' имеет приоритет 2, а 'test2' — приоритет 1.]
Если изменить приоритеты, например, 'test1' с приоритетом 1 и 'test2' с приоритетом 2, то вывод будет:
Тест 1Тест 2
- Пример четвертый: (Поддержка сторонних разработчиков)
Добавьте следующий код в
functions.php
function test1() { do_action( 'test_before' ); echo "Тест 1"; do_action( 'test_after' ); } add_action( 'test', 'test1' ); do_action( 'test' );
Вывод программы выше:
Тест 1
Теперь создадим простой плагин, чтобы проверить, как это работает для сторонних разработчиков.
- Создайте папку 'simple' в директории
/wp-content/plugins/
. - Создайте файл с именем 'simple.php' и добавьте следующий код.
/* * Plugin Name: Simple Plugin */ function test_callback_function() { echo "Из плагина"; } add_action( 'test', 'test_callback_function' );
Теперь активируйте наш Simple plugin из админ-панели WordPress.
Перейдите в меню "Плагины" и активируйте его.
После активации плагина вывод программы будет:
Тест 1Из плагина
[ПРИМЕЧАНИЕ: Если мы установим приоритет для действия нашего плагина от 1 до 9, то вывод будет таким:
Из плагинаТест 1
Потому что WordPress по умолчанию использует приоритет 10
для всех добавленных действий.]
Фильтры (Filters)
Проверьте следующие примеры:
Простой пример на PHP:
$data = array( 'one', 'two' ); print_r( $data );
Вывод программы выше:
Array ( [0] => one [1] => two )
- Пример первый: (Простое использование фильтра)
$data = apply_filters( 'my_filter_name', array( 'one', 'two' ) ); print_r( $data ); add_filter( 'my_filter_name', function( $old_data ) { return array( 'three', 'four' ); });
Вывод программы выше:
Array ( [0] => three [1] => four )
Здесь мы добавили фильтр my_filter_name
и изменили существующий вывод array( 'one', 'two' )
на array( 'three', 'four' )
без изменения файлов темы/плагина.

Спасибо @maheshwaghmare за такой простой трюк. Пожалуйста, напиши также про 'Фильтры'

@Rapti Извини за задержку. Сегодня вечером я добавлю ответ про фильтры. В будущем я напишу развернутую статью про хуки (Действия и Фильтры).

Почему бы не вызывать методы напрямую и не фильтровать данные там, где это нужно? В чем реальное назначение методов do_action, add_action и apply_filters?

Основное различие между действием (action) и фильтром (filter) можно описать следующим образом:
- Действие получает информацию, выполняет с ней какие-то операции и ничего не возвращает. Другими словами: оно действует на что-то и завершает работу, не возвращая данных обратно в вызывающий хук.
- Фильтр получает информацию, каким-то образом её изменяет и возвращает обратно. То есть: он фильтрует что-то и передаёт это обратно в хук для дальнейшего использования.
Или иначе:
- Действие прерывает поток выполнения кода, чтобы что-то сделать, а затем возвращается к обычному потоку, ничего не изменяя;
- Фильтр используется для изменения чего-то определённым образом, чтобы это изменение затем использовалось в дальнейшем коде.
Что-то, о чём идёт речь, — это список параметров, передаваемых через определение хука.
