Хуки в WordPress (фильтры и события)
В этой статье я собрал всю базовую информацию о хуках WordPress. А также постараюсь объяснить как работают хуки максимально просто. Принцип работы хуков не сложный, но далеко не все его понимают хорошо и это большое упущение, потому что хуки это очень мощный инструмент для изменения поведения ядра WP, создания плагинов и тем.
Есть два типа хуков:
- Фильтр (filter)
- Изменяет значение переменной — получает значение и возвращает его (изменённое или нет).
- Событие (action)
- Запускает произвольный код — колбэк функция прикрепленный к хуку сработает в момент срабатывания хука в коде.
К хукам (фильтрам или событиям) прикрепляются PHP функции их еще называют коллбэками (callback), затем эти функции сработают в момент срабатывания хука. Такое поведение в программировании называется перехват.
В функцию прикрепленную к хуку могут передаваться параметры (дополнительные данные). На основе этих данных в функции можно создавать какую-либо логику. Читайте ниже.
Простой пример хука-события (action):
// создадим функцию для хука - события
function echo_1(){
echo 'Hello';
}
// привяжем функцию к хуку
add_action( 'my_hook', 'echo_1' );
// создаем/используем/запускаем хук
do_action( 'my_hook' ); //> выведет на экран слово "Hello"
Пример с передачей параметра:
// создадим функции для событий
function echo_1( $data ){
echo $data[0] .' '. $data[1] .'!';
}
// привяжем функции к хуку
add_action( 'my_hook', 'echo_1' );
// создаем/используем/запускаем хук
do_action( 'my_hook', [ 'Привет', ' мир' ] ); //> выведет "Привет мир!"
В программной части фильтры и события — это одно и тоже, т.е. в коде и то и другое работает одинаково, можно например заменить функцию add_filter() на add_action() — все будет работать! Разделение нужно, потому что это разные вещи по смыслу.
Список всех хуков WP смотрите на странице «Все хуки WordPress».
Всего в WordPress их около 2000. Некоторые важные хуки я описал и продолжаю описывать, они находятся тут.
Как работают Фильтры в WordPress
Для работы фильтра используются две функции:
-
add_filter( hook_name, function, priority, args_num ) — добавляет/прикрепляет функцию к фильтру, которая будет вызвана в момент срабатывания фильтра. Такая функция называется «коллбэк-функция».
- apply_filters( hook_name, value, args... ) — создает хук-фильтр. Запускает прикрепленные к фильтру коллбэк-функцию.
На момент срабатывания хука в нём отработают только те коллбэки, которые уже были добавлены. Т.е. прикреплять коллбэк нужно до того как фильтр будет вызван с помощью apply_filters().
Пример
// коллбэк-функция
function my_filter_function( $str ){
return 'Здравствуйте '. $str;
}
// Прикрепим коллбэк к фильтру.
add_filter( 'my_filter', 'my_filter_function' );
// Вызов фильтра
$name = apply_filters( 'my_filter', 'Владимир' );
echo $name; //> Здравствуйте Владимир
Еще пример
Допустим, у нас есть функция text(), которая возвращает текст. Нам нужно сделать так, чтобы этот текст можно было изменять за пределами этой функции. Для этого назовем наш фильтр my_filter_name и создадим хук:
function text( $text ){
// удалим html теги из текста
$text = strip_tags( $text );
// возвращаем текст через фильтр.
return apply_filters( 'my_filter_name', $text );
}
// коллбэк функция
function my_filter_function( $text ){
// обрежем текст до 30 знаков
return mb_substr( $text, 0, 30 ) .'...';
}
// Прикрепим функцию к фильтру
add_filter( 'my_filter_name', 'my_filter_function' );
// Вызываем text()
// функция удалит из текста html теги — это сделает она сама с помощью strip_tags().
// А дальше обрежет текст — это сделает наш фильтр
$text = 'Lorem <b>Ipsum</b> is simply dummy text of the printing and typesetting industry.';
echo text( $text );
// выведет:
// Lorem Ipsum is simply dummy te...
Фильтров в WordPress много и вы наверняка с ними встречались в темах и плагинах. Популярные из них: the_content, body_class, sanitize_user, comment_form.
Как работают События в WordPress
Для работы события используются две функции:
-
add_action( hook_name, function, priority, args_num ) — добавляет/прикрепляет функции к событию, которое вызывается с помощью do_action(). Функция должна прикрепляться к событию до того, как событие произойдет. Нужно это, чтобы во время срабатывания события PHP функции уже были прикреплены к событию.
- do_action( hook_name, args... ) — это и есть событие. Запускает/вызывает добавленные к событию функции. Вызывается там, где должно сработать событие.
do_action() должна вызываться после add_action(), т.е. после того, как к событию добавлена функция, что логично...
Пример
Допустим, мы делаем тему и в каком-то месте темы нам нужно вызвать функцию, но мы заранее не знаем как функция будет называться. Т.е. пользователи сами будут добавлять функцию в это место.
Для этого в этом месте шаблона мы может вызвать не функцию а событие, назовем его my_action и затем прикрепить к этому событию функцию:
// создадим функцию для события
function my_action_function( $text ){
echo 'Событие "my_action" сработало сейчас.';
}
// Прикрепим функцию к событию 'my_action'. Это можно сделать в другом файле
// главное до того как событие сработает.
add_action( 'my_action', 'my_action_function' );
// Вызов самого события. Вставляем эту строку в то место темы где нужно,
// чтобы сработала прикрепленная к нему функция
do_action( 'my_action' ); //> на месте этого кода будет выведена надпись:
// 'Событие "my_action" сработало сейчас.'
С событиями вы тоже встречались их много и одни из самых популярных это: wp_head, wp_footer.
Приоритет хука
Приоритет важен когда к хуку прикрепляется несколько callback-функций. Приоритет определяет порядок, когда callback-функция будет выполняться по отношению к другим callback-функциям.
Приоритет указывается в третьем параметре для функции которая прикрепляет функцию к хуку:
add_action( 'init', 'hook_callback1', 8 ); add_action( 'init', 'hook_callback2', 9 );
Функция с приоритетом 8 выполнится раньше функции с приоритетом 9. Если приоритет не указан, то он равен 10 — приоритет по умолчанию.
Если две функции прикреплены к одном хуку с одинаковым приоритетом, то они будут выполняться в порядке их прикрепления.
Рассмотрим как работают приоритеты на примере:
add_action( 'init', 'run_me_late', 11 ); add_action( 'init', 'run_me_early', 9 ); add_action( 'init', 'run_me_normal' ); // приоритет 10 по умолчанию add_action( 'init', 'run_me_normal_two' ); // приоритет 10 по умолчанию
В момент срабатывания хука init функции выполняться в следующем порядке:
- run_me_early()
- run_me_normal()
- run_me_normal_two()
- run_me_late()
-
Как видно, чем больше число приоритета, тем позднее выполниться хук.
- Если приоритет не указан, как в первом примере, то он равен 10.
Для фильтров приоритеты работают точно также.
Параметры хука
В прикрепляемую коллбэк-функцию могут передаваться какие-то данные - параметры. Их можно использовать в момент срабатывания хука, чтобы создать какую-то логику.
Например, когда WordPress сохраняет запись, запускается событие save_post. Этот хук может передать два параметра: ID записи и объект записи:
do_action( 'save_post', $post->ID, $post );
По умолчанию передается только первый параметр $post->ID:
add_action( 'save_post', 'my_save_post_callback' );
function my_save_post_callback( $post_id ) {
// доступен один параметр
}
Однако можно указать что мы хотим получить 2 параметра. Для этого укажем четвертый параметр add_action():
add_action( 'save_post', 'my_save_post_callback', 10, 2 );
function my_save_post_callback( $post_id, $post ) {
// доступны 2 параметра
}
Ограничение в один параметр по умолчанию сделано для быстродействия системы хуков.
Для фильтров все работает аналогично
При создании фильтра в него можно передать сколько угодно параметров через запятую:
$str = apply_filters( 'my_filter', $str, $data1, $data2 );
Теперь, при добавлении коллбэка. Мы можем использовать эти параметры. Для этого нужно указать количество передаваемых параметров:
add_filter( 'my_filter', 'my_filter_function', 10, 3 );
3 - количество параметров, которые получит функция my_filter_function() в момент вызова.
Функция фильтра будет выглядеть так:
function my_filter_function( $str, $data1, $data2 ){
// Можем использовать $data1, $data2
return $str;
}
Удаление хука
Чтобы удалить хук, нужно изменить исходный код и удалить вызов хука, обычно это сделать невозможно, потому что хуки находятся в ядре или в плагине. Здесь мы поговорим о том, как можно удалить прикрепленные к хуку коллбэк-функции.
Для удаления функции привязанной к фильтру/событию, используется одна из функций:
Для справки. Это полностью одинаковые функции и обе они удаляют хук, а фильтр это или событие, в данном случае, значения не имеет. Так например, событии и фильтр мы можем удалить используя только функцию remove_filter() или только remove_action(). Но для понятности кода, все же лучше фильтры удалять с помощью remove_filter(), а события с помощью remove_action().
Для удаления хука нужно знать:
- Название хука, например
wp_footer. - Название прикрепленной функции, например
my_action_function. -
Приоритет выполнения хука, если он был установлен при создании хука. Если при создании приоритет не был установлен, то он равен 10 и при удалении его указывать не обязательно.
Если нужно удалить хук с приоритетом отличным от 10 и вы его не указали, то хук НЕ будет удален!
Пример удаления хука
Допустим где-то в плагине, к событию wp_footer прикреплена функция my_action_function, которая выводит текст в подвале темы:
add_action( 'wp_footer', 'my_action_function' );
function my_action_function( $text ){
echo 'Это текст в подвале!';
}
В теме нам нужно удалить это событие, чтобы текст в подвале не выводился. Для этого в файле темы functions.php можно прописать такой код:
remove_action( 'wp_footer', 'my_action_function' );
Важный момент: удалять хук нужно после того как он добавлен, но еще не отработал.
Еще пример удаления хука
Демонстрация добавления и удаления хука:
// добавляем функцию к событию my_action
add_action( 'my_action', 'my_action_function' );
function my_action_function( $text ){
echo 'Привет!';
}
// создаем событие
do_action( 'my_action' ); //> Привет!
// удаляем добавленное ранее событие
remove_action( 'my_action', 'my_action_function' );
// создаем событие еще раз
do_action( 'my_action' ); // ничего не выведет...
Удаление с учетом приоритета
Приоритет должен совпадать с тем который был задан при добавлении хука.
// если так добавлен add_filter( 'my_filter', 'function_name', 99 ); // то так нужно удалять remove_filter( 'my_filter', 'function_name', 99 );
Удаление хука статического метода класса
// так добавлен add_filter( 'my_filter', [ 'My_Class', 'static_method_name' ], 15 ); // так нужно удалять remove_filter( 'my_filter', [ 'My_Class', 'static_method_name' ], 15 );
Удаление хука не статического метода класса (если ЕСТЬ доступ к $this - экземпляру класса)
class A {
function __construct(){
add_action( 'my_action', [ $this, 'method_name' ], 15 );
}
function method_name(){
echo 'Привет!';
}
}
$class = new A(); // экземпляр
// для удаления нужно найти переменную в которую был сохранен
// экземпляр класса при создании, сейчас это $class
remove_action( 'my_action', [ $class, 'method_name' ], 15 );
Удаление хука не статического метода класса (если НЕТ доступа к $this - экземпляру класса)
Удалить хук для объекта класса к которому у нас нет доступа, стандартными функциями WP невозможно. Но сделать это можно, используя следующие кастомные функции:
<?php
/**
* Remove Class Action Without Access to Class Object
*
* @see remove_object_filter()
*/
function remove_object_action( string $hook_name, $static_callback, $priority = null ): bool {
return remove_object_filter( $hook_name, $static_callback, $priority );
}
/**
* Remove filters without access to class object (instance).
*
* To use remove_filter() function you need to have access to class instance,
* or the filter should be added using static method as hook callback.
* This function allows you to remove filters with callbacks you don't have access to.
*
* @param string $hook_name Filter name to remove.
* @param string|array $static_callback Hook callback where instance represented as class name.
* Eg: [ '\Space\My_Class', 'my_method' ] OR '\Space\My_Class' to remove all methods added to hook.
* @param int|null $priority (optional) Priority of the filter. If not set all hooks with any priority will be removed.
*
* @return bool Whether the hook is removed.
*
* @requires WP 4.7+
* @author Kama (wp-kama.com)
* @version 2.0
*/
function remove_object_filter( string $hook_name, $static_callback, $priority = null ): bool {
if( is_string( $static_callback ) ){
// '\Space\My_Class::my_method' or '\Space\My_Class'
$static_callback = explode( '::', $static_callback ) + [ '', '' ];
}
$found = _find_hook_callback_instances( $hook_name, $static_callback, $priority );
$res = 0;
foreach( $found as $item ){
$callback = [ $item['instance'], $item['method'] ];
$res += (int) remove_filter( $hook_name, $callback, $item['priority'] );
}
return (bool) $res;
}
/**
* Finds the instance of the object whose specified method is added for the specified hook.
*
* To use remove_filter() function you need to have access to class instance,
* or the filter should be added using static method as hook callback.
* This function allows you to find class instance that was used when the hook was added.
*
* @param string $hook_name Filter name.
* @param string|array $static_callback Hook callback where instance represented as class name.
* Eg: [ '\Space\My_Class', 'my_method' ]
* or [ '\Space\My_Class' ] to get all methods added for the hook.
* @param int|null $priority (optional) Priority of the filter.
*
* @return array{ instance: object|string, method:string, priority:int }[]
*
* @author Kama (wp-kama.com)
* @version 1.1
*/
function _find_hook_callback_instances( string $hook_name, array $static_callback, $priority = null ): array {
global $wp_filter;
/** @var \WP_Hook $wp_hook WP hooks. */
$wp_hook = $wp_filter[ $hook_name ] ?? null;
if( empty( $wp_hook->callbacks ) ){
return [];
}
$find_class_name = ltrim( $static_callback[0], '\\' ); //> \Space\My_Class >>> Space\My_Class
$find_method_name = $static_callback[1] ?? '';
$found = [];
foreach( $wp_hook->callbacks as $the_priority => $hooks_data ){
foreach( $hooks_data as $hook_data ){
$real_callback = $hook_data['function'] ?? null;
if( ! is_array( $real_callback ) ){
continue;
}
[ $object, $the_method_name ] = $real_callback;
$class_name = is_object( $object ) ? get_class( $object ) : $object;
if(
$class_name !== $find_class_name
|| ( $find_method_name && $the_method_name !== $find_method_name )
|| ( null !== $priority && $the_priority !== $priority )
){
continue;
}
$found[] = [
'instance' => $object,
'method' => $the_method_name,
'priority' => $the_priority,
];
}
}
return $found;
}
Пример использования.
Допустим у нас есть такой класс:
namespace My\Space;
class MyClass {
public function __construct() {
add_action( 'some_action_hook', [ $this, 'my_method' ], 11 );
add_filter( 'some_filter_hook', [ $this, 'my_method' ], 11 );
}
public function my_method() {
die( 'my_method trigered: '. current_filter() );
}
}
Мы инициализировали класс, в результате чего добавилось 2 хука:
new \My\Space\MyClass();
Теперь, удалить хуки этого класса, через стандартные функции WP будет невозможно, потому что для удаления хука, нам нужно иметь доступ к конкретному экземпляру класса, а его у нас нет. Но благодаря функциям выше, мы можем это сделать, просто указав название класса, метода и приоритет.
Рассмотрим все варианты как можно вызвать функцию, чтобы удалить хук:
remove_object_action( 'some_action_hook', [ 'My\Space\MyClass', 'my_method' ], 11 ); remove_object_action( 'some_action_hook', [ '\My\Space\MyClass', 'my_method' ], 11 ); remove_object_action( 'some_action_hook', [ '\\My\\Space\\MyClass', 'my_method' ], 11 ); remove_object_action( 'some_action_hook', [ \My\Space\MyClass::class, 'my_method' ], 11 ); remove_object_action( 'some_action_hook', '\My\Space\MyClass::my_method', 11 ); remove_object_action( 'some_action_hook', 'My\Space\MyClass::my_method', 11 ); // или аналогично для фильтров remove_object_filter( 'some_filter_hook', [ 'My\Space\MyClass', 'my_method' ], 11 ); // etc...
Или если нужно удалить все хуки, независимо от приоритета, мы можем пропустить параметр $priority:
remove_object_action( 'some_action_hook', [ 'My\Space\MyClass', 'my_method' ] );
Удаление всех хуков, которые добавляет указанных класс
Этот пример показывает как удалить все добавленных хуки от определенного класса. Здесь не имеет значения какой метод класса добавлен к хуку, будут удалены все указанные хуки, указанного класса.
<?php
/**
* Remove current action or filter from plugin
*
* @param string $class_name Class name enqueueing the action.
* @param null $action_name Action name.
*/
function remove_plugin_action( $class_name, $action_name = null ) {
global $wp_filter;
if ( null === $action_name ) {
$action_name = current_action();
}
/** @var WP_Hook $hooks WP hooks. */
$hooks = $wp_filter[ $action_name ];
$callbacks = $hooks->callbacks;
foreach ( $callbacks as $priority => $actions ) {
foreach ( $actions as $action ) {
$function = $action['function'];
if ( is_array( $function ) ) {
$callback = $function[0];
if (
( is_object( $callback ) && get_class( $callback ) === $class_name ) ||
( is_string( $callback ) && $callback === $class_name )
) {
remove_action( $action_name, $function, $priority );
}
}
}
}
}
// Example of usage.
/**
* Enqueue Google maps scripts only on certain pages.
*/
function action_google_maps_script() {
if ( ! ( is_page_template( 'templ-contact.php' ) ) ) {
remove_plugin_action( 'PageSpeed_Optimization' );
}
}
add_action( 'wp_enqueue_scripts', 'action_google_maps_script', 0 );
Удаление хука добавленного анонимной функцией (closure)
Удалить хук с замыканием не так просто, например такой код не сработает:
add_action( 'my_action', function(){ echo 'Привет!'; } );
remove_action( 'my_action', function(){ echo 'Привет!'; } ); // не работает!
Надежно удалить хук с использованием замыкания, можно только если замыкание создавалось в переменную и у нас есть доступ к этой переменной:
$my_func = function(){
echo 'Привет!';
};
add_action( 'my_action', $my_func );
remove_action( 'my_action', $my_func ); // Работает!
НЕ надежный, но все же способ удалить хук с замыканием, когда у нас нет доступа к замыканию:
/**
* Removes the hook when it has been added by a closure.
* The accuracy of the function is not guaranteed - the first hook
* that matches the priority and the number of hook arguments will be removed.
*
* @param string $name
* @param int $priority
* @param int $accepted_args
*/
function remove_closure_hook( $name, $priority = 10, $accepted_args = 1 ): bool {
global $wp_filter;
if( empty( $wp_filter[ $name ]->callbacks[ $priority ] ) ){
return false;
}
$callbacks = & $wp_filter[ $name ]->callbacks[ $priority ];
// Find our hook.
// It is not always possible to identify it unambiguously, but
// at least we know that it was created with a closure
// and we know it's priority and number of parameters.
foreach( $callbacks as $key => $hook ){
if( ! ( $hook['function'] instanceof Closure ) ){
continue;
}
if( $hook['accepted_args'] !== $accepted_args ){
continue;
}
// remove
unset( $callbacks[ $key ] );
// first suitable only
return true;
}
return false;
}
Пример использования:
add_action( 'my_action', function(){
echo 'Привет!';
} );
do_action( 'my_action' ); // Привет!
remove_closure_hook( 'my_action', 10, 1 );
do_action( 'my_action' ); // (пусто)
Создание своего хука
При написании плагина, в него можно и нужно добавлять хуки, чтобы дать возможность пользователям внедряться в код плагина, не меняя код самого плагина. Так, прикрепляя коллбэки к вашему хуку пользователи вашего плагина смогут изменять его код из кода другого плагина или темы.
Чтобы создать событие или фильтр в коде, к которому потом можно будет добавлять функции, используется функция
- do_action() — для событий.
- apply_filters() — для фильтров.
Синтаксис у этих функций такой:
do_action( $tag, $arg_a, $arg_b, ... ); apply_filters( $tag, $value, $arg_a, $arg_b, ... );
- $tag(строка) (обязательный)
- Название хука.
- $value(строка/массив/число/объект/логический) (обязательный)
- Значение, которое будет передаваться функции в её первом аргументе — значение, которое нужно отфильтровать.
- $arg_a(строка/массив/число/объект/логический)
- Значение аргумента.
- $arg_b(строка/массив/число/объект/логический)
- Значение еще одного аргумента.
Пример создания хука-события
Допустим, у нас есть плагин опроса и при голосовании хорошо бы добавить событие этого голосования. Чтобы можно было из другого кода подключиться к нашему плагину и, допустим, при голосовании, записать какие-то данные пользователя к себе в базу данных. Такой функционал может не предусматриваться плагином, но он может пригодится пользователям вашего плагина и при наличии хука, они легко его допишут.
Итак, у нас есть функция плагина add_vote() - записывает голос, в конец этой функции добавим событие:
function add_vote(){
// код функции
// тут определяется ID опроса - $poll_id и выбранный ответ - $answer
// передадим эти данные в хук.
// создаем хук
do_action( 'my_plugin_add_vote', $poll_id, $answer );
}
Теперь, разработчик темы или другого плагина может использовать этот хук и выполнить в момент события нужные ему действия.
add_action( 'my_plugin_add_vote', 'my_add_vote_logic', 10, 2 );
function my_add_vote_logic( $poll_id, $answer ){
global $wpdb;
// запишем в таблицу логов, заметку что кто-то проголосовал
$wpdb->insert( $wpdb->log_table, [
'user_id' => 5,
'log_massage' => 'Проголосовали за опрос '. $get_poll( $poll_id )->name
] );
}
Функции хуков в WordPress
| do_action() | Создает событие (возможность запустить php функции в нужный момент работы кода). Подключать php функцию к событию нужно с помощью add_action(). |
| do_action_ref_array() | Создает событие (хук), на который затем можно прикрепить PHP функции. Аргументы передаются в виде массива. |
| do_action_deprecated() | Fires functions attached to a deprecated action hook. |
| add_action() | Прикрепляет указанную PHP функцию на указанный хук. Указанная функция сработает в момент события, которое в свою очередь запускается с помощью do_action(). |
| remove_action() | Удаляет хук (событие или фильтр). Удаляет функцию прикрепленную к указанному хуку. |
| remove_all_actions() | Удаляет все хуки у указанного события. |
| did_action() | Получает число, сколько раз было вызвано указанное событие (хук). |
| current_action() | Retrieves the name of the current action hook. |
| doing_action() | Проверяет обрабатывается ли в текущий момент указанный хук (фильтр, событие). |
| has_action() | Проверяет была ли зарегистрирована функция для хука-события. |
| apply_filters() | Применяет прикрепленную к указанному фильтру PHP функцию. |
| apply_filters_ref_array() | Выполняет функции прикрепленные к указанному хуку (фильтру). Параметры передаются в массиве. Позволяет передать параметр по ссылке. |
| apply_filters_deprecated() | Fires functions attached to a deprecated filter hook. |
| add_filter() | Прикрепляет указанную PHP функцию к указанному хуку-фильтру. Так, во время срабатывания фильтра значение будет обработано указанной PHP функцией. |
| remove_filter() | Удаляет указанную функцию прикрепленную к указанному фильтру. |
| remove_all_filters() | Удаляет все хуки у указанного фильтра. |
| current_filter() | Получает название текущего фильтра (который выполняется в момент вызова этой фукнции). |
| has_filter() | Проверяет была ли прикреплена к указанному фильтру какая-нибудь функция. Можно указать название конкретной функции. |
| doing_filter() | Проверяет обрабатывается ли в текущий момент указанный хук (фильтр, событие). |
Вспомогательные WordPress функции для фильтров
В WordPress есть специальные функции, которые упрощают работу с фильтрами.
| Функция | Описание |
|---|---|
| __return_true() | Просто возвращает true. Вспомогательная функция WordPress. |
| __return_false() | Просто возвращает false. Вспомогательная функция WordPress. |
| __return_zero() | Просто возвращает 0. Вспомогательная функция WordPress. |
| __return_empty_string() | Просто возвращает пустую строку: ''. Вспомогательная функция WordPress. |
| __return_empty_array() | Просто возвращает пустой массив: array(). Вспомогательная функция WordPress. |
| __return_null() | Просто возвращает null. Вспомогательная функция WordPress. |
Например, мы может отключить все стандартные виджеты WordPress с помощью фильтра load_default_widgets, так:
function is_load_default_widgets(){
return false;
}
add_filter( 'load_default_widgets', 'is_load_default_widgets' );
Или можно не создавать отдельную функцию которая вернет false, а использовать уже готовую функцию из ядра WordPress: __return_false():
add_filter( 'load_default_widgets', '__return_false' );
Чтобы было понятнее как это работает, давайте посмотрим на вызов фильтра load_default_widgets:
function wp_maybe_load_widgets(){
if ( ! apply_filters( 'load_default_widgets', true ) )
return;
require_once( ABSPATH . WPINC . '/default-widgets.php' );
add_action( '_admin_menu', 'wp_widgets_add_menu' );
}
При вызове функции wp_maybe_load_widgets() срабатывает фильтр. По умолчанию он всегда возвращает true и условие не выполняется — виджет подключаются. А в примерах выше мы возвращаем false и условие выполняется — виджеты не подключаются.
Это демо пример из кода WordPress, чтобы объяснить принцип работы. В практике его лучше не использовать, для отключения виджетов используйте код из описания функции unregister_widget().
Аналогичный пример
Аналогичным образом можно выключить возможность публиковать записи по протоколу xmlrpc. Которой, кстати по умолчанию включен, но им мало кто пользуется.
// отключим публикацию по xmlrpc add_filter( 'xmlrpc_enabled', '__return_false' );
Еще один пример
Закроем возможность сброса пароля, с помощью фильтра allow_password_reset:
add_filter( 'allow_password_reset', '__return_false' );
Теперь все пользователи не смогут сбрасывать пароли на сайте.
Список всех хуков WordPress
Получить список всех хуков может понадобится. В процессе разработки или при поиске ошибок.
Как я упоминал выше все хуки записываются в общий массив, а точнее в глобальную переменную $wp_filters. К слову, если удалить из $wp_filters элемент массива (хук), то хук перестанет работать...
Следующий код выведет список всех хуков (фильтров и событий), которые зарегистрированы на момент вызова этого кода:
/**
* Выводит на экран список всех хуков WordPress и функций к ним прикрепленных.
*
* @param string $hook_name Название хука, список фукнций которого нужно вывести.
*
* @version 3.0
*/
function get_hooks_list( string $hook_name = '' ): string {
global $wp_filter;
$wp_hooks = $wp_filter;
// для версии 4.4 - переделаем в массив
if( is_object( reset( $wp_hooks ) ) ){
foreach( $wp_hooks as & $object ){
$object = $object->callbacks;
}
unset( $object );
}
$hooks = [];
if( $hook_name ){
$hooks[ $hook_name ] = $wp_hooks[ $hook_name ] ?? null;
if( ! is_array( $hooks[ $hook_name ] ) ){
return "Nothing found for the '$hook_name' hook";
}
}
else{
$hooks = $wp_hooks;
ksort( $wp_hooks );
}
$output = '';
foreach( $hooks as $name => $hook_data ){
ksort( $hook_data );
$output .= "\nHook\t<b>$name</b>\n";
foreach( $hook_data as $priority => $hooksdata ){
$output .= $priority;
foreach( $hooksdata as $key => $hdata ){
$func = $hdata['function'];
if( is_array( $func ) ){
if( is_object( $func[0] ) ){
$func_name = get_class( $func[0] ) . '->' . $func[1];
}
else {
$func_name = $func[0] . '::' . $func[1];
}
}
elseif( $func instanceof Closure ){
$func_name = "Closure_$key";
}
else {
$func_name = $key;
}
$output .= "\t$func_name()\n";
}
}
}
return sprintf( '<%1$s>%2$s</%1$s>', 'pre', $output );
}
Пример использования:
echo get_hooks_list(); /* Получим список такого формата: хук wp_enqueue_scripts 10 lambda_2 99 theme_scripts_styles хук wp_footer 0 0000000072b7ec0d00002b862c2211a0enqueue_jquery_if_need 10 0000000072b7edb400002b862c2211a0footer_scripts 0000000072b7eb7b00002b862c2211a0main_js 20 wp_print_footer_scripts 99 0000000072b7ec0d00002b862c2211a0add_script_to_footer 0000000072b7eb1600002b862c208180 question_close_ajax_js add_question_rating_ajax_js add_comment_rating_ajax_js 999 0000000072b7edb600002b862c2211a0footer_script 1000 wp_admin_bar_render 9999999999 0000000072b7eb0b00002b862c208180 ... и т.д. ... */
А так выглядит элемент массива в самой переменной $wp_filter:
Как получить функции прикрепленные к указанному хуку?
Часто бывает нужно посмотреть, какие функции прикреплены к отдельному фильтру или событию.
Код выше позволит это сделать, для этого нужно указать в нем параметр $hook_name:
echo get_hooks_list( 'the_title' ); /* Получим: хук the_title 10 wptexturize convert_chars trim func_title_add_brackets 11 capital_P_dangit */
Другой вариант - это просто получить данные массива
Используем глобальную переменную $wp_filters. В ней хранятся данные всех хуков.
Данные в $wp_filters добавляются по ходу обработки кода, поэтому имеет большое значение когда используется переменная $wp_filters: например, если её использовать в начале файла темы functions.php, то в ней будут все функции хуков который были добавлены до подключения этого файла, но не будет добавленных в этом файле или позднее.
/**
* Выводит список функций прикрепленных к указанному хуку
* @param (str) $hook Название хука, функции которого нужно вывести.
*/
function print_filters_for( $hook ){
global $wp_filter;
$data = isset( $wp_filter[$hook] ) ? $wp_filter[$hook] : "Хук `$hook` не найден...";
echo '<pre>', print_r( $data, 1 ) .'</pre>';
}
Теперь, чтобы вывести список всех функций/методов прикрепленных к фильтру или событию нужно вызвать эту функцию, и указать ей название хука.
Например, получим все функции добавленные к событию wp_footer. В индексе callbacks мы получим все функции прикрепленные к хуку, в порядке приоритета их вызова.
print_filters_for( 'wp_footer' ); /* Выведет: WP_Hook Object ( [callbacks] => Array ( [0] => Array ( [echo_ads_tpls] => Array ( [function] => echo_ads_tpls [accepted_args] => 1 ) ) [20] => Array ( [wp_print_footer_scripts] => Array ( [function] => wp_print_footer_scripts [accepted_args] => 1 ) ) [99] => Array ( [question_close_ajax_js] => Array ( [function] => question_close_ajax_js [accepted_args] => 1 ) [add_question_rating_ajax_js] => Array ( [function] => add_question_rating_ajax_js [accepted_args] => 1 ) ) [1000] => Array ( [wp_admin_bar_render] => Array ( [function] => wp_admin_bar_render [accepted_args] => 1 ) ) ) [iterations:WP_Hook:private] => Array() [current_priority:WP_Hook:private] => Array() [nesting_level:WP_Hook:private] => 0 [doing_action:WP_Hook:private] => ) */
Рекомендации
Именование динамических хуков
В документации WordPress есть интересная заметка об именовании динамических хуков.
Используйте фигурные скобки для переменных в названии динамических хуков:
// Правильно:
do_action( "{$new_status}_{$post->post_type}", $post->ID, $post );
// Неправильно:
do_action( $new_status . '_' . $post->post_type, $post->ID, $post );
Это нужно для упрощения анализа кода, для быстрого поиска в редакторе кода, для удобной генерации документации по хукам и т.д.
Комментарии к динамическому хуку (PHPDoc)
Также, в PHP комментариях к динамическому хуку рекомендуется писать возможное варианты конкретного имени хука. Формат такой записи выглядит так:
/**
* Fires before a specified login form action.
*
* Possible hook names include:
*
* - `login_form_checkemail`
* - `login_form_confirm_admin_email`
* - `login_form_confirmaction`
* - `login_form_entered_recovery_mode`
* - `login_form_login`
* - `login_form_logout`
* - `login_form_lostpassword`
* - `login_form_postpass`
* - `login_form_register`
* - `login_form_resetpass`
* - `login_form_retrievepassword`
* - `login_form_rp`
*
* @since 2.8.0
*/
do_action( "login_form_{$action}" );
—
Быстрые и дешевые лайки на любые посты в Instagram можно приобрести на сайте Doctor SMM с гарантией на выполнение заказа. Только здесь Вы найдете ресурс на свой вкус! На сайте представлен широкий выбор формата лайков: русские, англоязычные, автолайки, тв-лайки, микс и пр. Делайте заказ сейчас и получайте выгодные оптовые скидки!