Хуки WordPress — это полезный инструмент, предназначенный для разработчиков, создающих плагины и темы WordPress. Фактически, они настолько полезны, что создатели WordPress используют их во всем ядре WordPress. Но что такое хуки WordPress и как их использовать? Давайте разберемся вместе.
Что такое хуки в WordPress?
Короче говоря, хуки WordPress — это фрагменты кода WordPress, которые захватывают и выполняют фрагменты других фрагментов кода WordPress. По сути, они позволяют разработчикам легко переключаться между различными файлами в своих темах и плагинах.
Хуки WordPress входят в состав ядра WordPress . Каждая тема и плагин также используют их.
В чем смысл использования хуков WordPress
Основная цель хуков в WordPress — позволить разработчикам изменить работу системы управления контентом без изменения основных файлов WordPress. Зачастую вам нужно в коде отслеживать какие-то события, которые происходят в системе, например, процесс загрузки темы или отправки сообщения с помощью AJAX. Либо вы хотите поменять вывод контента, добавив в его середину вывод подобных записей. Вот тут-то и пригодятся хуки, которые позволяют это отследить.
Поскольку WordPress имеет открытый исходный код, вы можете найти все основные хуки либо в самом коде, либо в массе открытых источников, например, здесь на русском или здесь на английском. Вы очень удивитесь, увидев список стандартных для WordPress хуков. Их количество впечатляет.
С точки зрения перевода с английского хуки - это программные крючки в виде функций, за которые могут зацепиться другие функции PHP. Они реализованы в виде коллбеков (функций обратного вызова), которые что-то делают с данными или отображением до того, как пользователь увидит данные.
Два типа хуков WordPress
Есть два основных типа хуков WordPress, которые вам нужно изучить:
- Хуки действий или событий (action hooks) WordPress
- Фильтры (filter hooks) WordPress
Хуки действий позволяют вам добавлять, удалять или менять определённые функции. А хуки фильтров отвечают за добавление, удаление и изменение информации.
Разница между хуками действий WordPress и хуками фильтров
Самый простой способ отличить два типа хуков WordPress — это запомнить то, что хуки фильтров возвращают значения, а хуки действий никаких значений не возвращают, а перехватывают действия и меняют их с помощью коллбэков (callback). Давайте подробнее:
- Хук типа фильтр (filter) изменяет значение переменной — получает значение и возвращает его (изменённое или нет). Их можно рассматривать как перехватчики для предварительной обработки данных. Хук filter может фильтровать результаты, возвращаемые из запроса к базе данных, так, чтобы они содержали только записи с фамилией «Пупкин». Этот хук фильтра следует вызывать до вызова фактического запроса к базе данных, заранее сообщая WordPress, что ему необходимо удалить нерелевантные результаты перед их возвратом.
- Хук типа действие, или событие (action) запускает произвольный код в виде вызова коллбэк-функции в момент срабатывания хука в коде WordPress. Хуки типа action в WordPress можно рассматривать как получение чего-либо через код. Типичным примером перехватчика действий является вставка дополнительного файла CSS на страницу сайта, чтобы она выглядела по-другому.
На самом деле функции-коллбэки прикрепляются и к хукам-фильтрам и к хукам-действиям (событиям). Эти функции срабатывают в момент срабатывания хука, перехватывая "инициативу", т.е. запуская свой код и изменяя некое поведение либо добавляя что-то.
Этот процесс не предполагает редактирования ядра WordPress, что является безусловным плюсом. Также это гарантирует, что в момент обновления WordPress ваш код никуда не "улетит".
Оба типа хуков необходимо зарегистрировать в WordPress перед их использованием. Для этого используют функции add_action()
для хука action и add_filter()
для хука filter. Легко запоминается, не так ли?
Также имеются соответствующие функции удаления действий (событий) и фильтров. Их можно использовать для исключения функции из цепочки обратных вызовов. Они часто содержатся в условных операторах WordPress PHP. Как и функции добавления, они легко запоминаются:remove_action()
и remove_filter()
.
В функцию прикрепленную к хуку, могут передаваться параметры (дополнительные данные). На основе этих данных в функции можно создавать какую-либо логику. Все, что вы указываете в этих функциях, запускается, когда ваш сайт открывается пользователем. В WordPress есть внутренний генератор, который объединяет для вас все эти действия и фильтры.
Создаем хук типа action в WordPress
Например, вам нужно добавить сообщение для пользователей корпоративного сайта о необходимости использования корпоративной почты для входа типа @mycorporation.com
. Для начала нужно определиться с тем, какой хук в системе хуков WordPress отвечает за вход пользователя в админку. Из всех хуков, которые мы можем найти, используя поиск по слову "login", наиболее подходящими выглядят хуки login_init (срабатывает при инициализации формы входа в систему), login_header (срабатывает сразу после открывающего тега <body>
на странице входа/авторизации (wp-login.php), до вывода формы) и login_footer (срабатывает после вывода формы на странице входа/авторизации (wp-login.php). Все эти данные мы можем получить, прочитав информацию по ссылкам. В результате несложного анализа можно сделать вывод, что, если сообщение нужно вывести ДО формы, то лучше использовать хук login_header
, если после формы, то хук login_footer
. Оба хука относятся к типу action, поэтому будем использовать функцю add_action()
.
Разместим предупреждение после формы, поэтому код такой:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function add_email_reminder() { ?> <p class="email-message">Не забудьте использовать адрес электронной почты <mark>@mycorporation.com</mark> в качестве имени пользователя!</p> <style> .email-message { max-width: 500px; margin: 20px auto; padding: 15px; color: #fff; text-align: center; font-size: 1.1em; background: #2c7ba5; } .email-message mark { display: inline-block; background-color: #fff; padding: 2px 5px; } </style> <?php } add_action( 'login_footer', 'add_email_reminder' ); |
В результате под формой входа мы увидим сообщение:
Типичным использованием хука action является регистрация пользовательских типов записей, широко применяемая в WordPress для расширения функционала темы, например, в случае необходимости добавлять отзывы. В этом случае хук выглядит примерно так:
1 2 3 4 5 6 | add_action( 'init', 'mytheme_register_post_type' ); function mytheme_register_post_type(){ //... код ... register_post_type( 'testimonial', $args ); } |
Также на хук init
можно добавить, например, функцию, регистрирующую новый блок для плагина, описанного в статье "Создание своего Gutenberg-блока для WordPress на основе wordpress-create-block".
Создаем хук типа filter в WordPress
Для создания фильтра вы должны выбрать какой-то хук, который относится к фильтрам в WordPress. Очень много фильтров существует для контента. А в контенте мы можем управлять заголовками, картинками, всем текстом записи. Сейчас давайте посмотрим, как решить с помощью хука типа filter проблему вывода заголовков архивов, меток и категорий.
Обычно заголовок архива может выглядеть, как "Рубрика: Популярная психология" или "Метка: Решение проблемы". Нам же надо оставить только заголовок.
Убираем слова "Архив", "Метка" и "Категория":
1 2 3 4 5 6 7 8 9 10 11 12 13 | add_filter( 'get_the_archive_title', 'mytheme_remove_name_cat' ); function mytheme_remove_name_cat( $title ){ $title = single_term_title('', false ); return $title; } //или с помощью регулярных выражений function remove_archive_title( $title ){ return preg_replace('~^[^:]+: ~', '', $title ); } add_filter( 'get_the_archive_title', 'remove_archive_title'); |
Добавлять этот хук нужно в файл functions.php
вашей темы.
Для того чтобы полностью удалить заголовок рубрики или архива можно использовать код для того же хука, но с возвратом пустой строки:
1 | add_filter( 'get_the_archive_title', '__return_empty_string' ); |
Т.е. в этом случае у вас совсем не будет выведено ни название архива, ни метки, ни рубрики, а не только удалится слово, предваряющее это название (заголовок).
Кстати, ядро WordPress определяет несколько вспомогательных функций для работы с подобными фильтрами:
__return_true()
— возвращает true__return_false()
— возвращает false__return_zero()
— возвращает 0__return_empty_string()
— возвращает пустую строку__return_empty_array()
— возвращает пустой массив__return_null()
— возвращает null
Например, при использовании фильтра comments_open
можно закрыть везде комментарии, просто записав строку:
1 | add_filter( 'comments_open', '__return_false' ); |
Кроме того, с помощью хуков фильтров и действий мы можем использовать фильтры для отключения популярных ныне блочного редактор Гутенберг и блочных виджетов.
Отключаем редактор Gutenberg и блочные виджеты в WordPress
Редактор Гутенберг является основным с версии WordPress 5.0. Но для тех, кто давно работает с WordPress, довольно часто предпочтительным является предыдущий редактор. Вы можете вернуть его, установив плагин Classic Editor или добавив такой код в файл functions.php
1 | add_filter( 'use_block_editor_for_post_type', '__return_false' ); |
Либо редактор Гутенберг можно отключить для определенного типа записи:
1 2 3 4 5 6 7 8 | add_filter( 'use_block_editor_for_post_type', function( $use, $post_type ){ if( 'movie' === $post_type ) { $use = false; // отключаем тип записи movie } return $use; }, 100 ); |
Вместо этого в момент регистрации типа записи мы можем указать параметр 'show_in_rest' => false
:
1 2 3 4 5 6 7 8 | register_post_type( 'movie', array( 'show_in_rest' => false, // false - редактор Гутенберг отключен, true – включен //...остальной код... ) ); |
1 | add_filter('use_widgets_block_editor', '__return_false' ); |
Например, такую строку нужно указать при создании виджета в WordPress в классическом стиле.
Так что фильтры могут делать многие вещи в вашем коде.
Множество примеров использования хуков-фильтров вы найдете в статье "Полезные функции при работе с темой для Woocommerce".
Последовательность срабатывания хуков
В зависимости от того, какой процесс запускает WordPress, порядок выполнения хуков будет отличаться. Вы можете посмотреть тут, какова последовательность срабатывания хуков в админке, фронтенде или, например, при загрузке файлов темы. Поэтому важно, чтобы вы привязывали свой хук к правильному действию (событию, или action) или фильтру (filter). Также можно указывать в качестве 3-го параметра приоритет вызова вашей функции.
По умолчанию для фильтров и действий присваивается приоритет в виде цифры 10. Вы можете увеличить приоритет, указав, например, 100 или уменьшить, добавив 1. Нельзя указывать дробные или отрицательные числа. Т.е. ни 0.5, ни -100 не подойдут.
Приоритет важен, когда к хуку прикрепляется несколько callback-функций. Приоритет определяет порядок, в котором будут вызваны эти callback-функции.
Приоритет указывается в так:
1 2 3 4 5 6 7 8 9 10 11 12 13 | add_action( 'init', 'func_hook1' ); add_action( 'init', 'func_hook2', 5 ); add_action( 'init', 'func_hook3', 100 ); function func_hook1(){ echo '<p>Hook 1</p>'; } function func_hook2(){ echo '<p>Hook 2</p>'; } function func_hook3(){ echo '<p>Hook 3</p>'; } |
В коде, приведенном выше, сначала мы увидим вывод абзаца с текстом Hook2, затем Hook1 и в конце Hook3. Это происходит потому, что 5 - более низкий приоритет для функции func_hook2
, чем 10 по умолчанию для func_hook1
, поэтому она отрабатывает первой, а у func_hook3
самый высокий приоритет - 100, поэтому она отрабатывает последней.
Удаление хуков
Удаление хуков иногда бывает не менее полезным, чем их добавление.
Удаляем все действия или фильтры
Вы можете удалить все ваши хуки, привязанные к какому-либо действию или фильтру с помощью функций remove_all_actions( $tag, $priority );
или remove_all_filters( $tag, $priority );
. В качестве параметров в этих функциях используются:
- $tag (строка, обязательный) - название фильтра, все хуки которого нужно удалить.
- $priority (число) - приоритет хуков, которые нужно удалить. По умолчанию: false,т.е. отсутствует. Тут есть варианты:
- если вы указываете некое число, то будут удалены только хуки с этим приоритетом.
- если не указываете (оставить false), то будут удалены абсолютно все прикрепленные к фильтру хуки.
Если мы запишем для кода, приведенного выше, такую строку:
1 | remove_all_actions( 'init' ); |
то вообще не увидим вывод абзацев.
Для удаления абзаца с текстом Hook3, нужно написать
1 | remove_all_actions( 'init', 100 ); |
Нужно быть очень аккуратным при удалении всех действий (action) или фильтров (filter) определенного типа, т.к. вы можете лишить свой сайт полезных функций. Например, если удалить все фильтры, привязанные к контенту строкой
1 | remove_all_filters( 'the_content' ); |
то вы лишите, например, вывод изображений атрибута srcset
, а также можете убрать действие плагинов типа вывода подобных постов.
Удаляем определенные действия или фильтры
Поэтому при необходимости удаления каких-либо action или filter, нужно смотреть на функцию их добавления в теме или плагине и использовать приоритет, либо удалять конкретно данное действие (событие) или фильтр с помощью функций remove_action( $tag, $function_to_remove, $priority );
или remove_filter( $tag, $function_to_remove, $priority );
. В них используют такие параметры:
- $tag (строка, обязательный) - название действия или фильтра, функцию которого нужно удалять.
- $function_to_remove (строка, обязательный) - название функции, которую нужно удалить.
- $priority (число, по умолчанию 10) - приоритет хука (функции), который был установлен во время добавления.
Например, мы передумали добавлять сообщение в футере формы авторизации.
1 | remove_action( 'login_footer', 'add_email_reminder' ); |
Если бы мы указали приоритет выполнения хука, например 20, то строка видоизменилась бы так:
1 | remove_action( 'login_footer', 'add_email_reminder', 20 ); |
С фильтрами подход аналогичный, только используем функцию remove_filter()
.
Добавляем собственный, или кастомный хук
Как и в случае со стандартными хуками, мы можем добавлять хуки типа action или filter. В каждом из этих случаев нужно использовать несколько разные функции.
Кастомный хук типа action
Добавление кастомного хук типа action предполагает использование функций add_action()
для определения названия хука и функции, которую он будет вызывать и do_action()
для выполнения этого хука в нужном месте темы или плагина.
Cобственный, или кастомный хук - это некая функция, которая выполняется в определенный момент времени. Такие хуки очень удобно использовать при написании темы, когда необходимо вывести определенные данные при разных настройках темы например. Или когда нужно вставить в код какие-то блоки. Для этого можно использовать и обычные функции, но с хуками бывает намного удобнее распределять код по отдельным файлам.
Обычно весть дополнительный функционал для темы записывают в файле functions.php, но вместо этого можно создать папку theme-hooks и в ней файл header-hooks.php, например, а потом подключить его в файл functions.php строкой:
1 | require get_template_directory() . '/theme-hooks/header-hooks.php'; |
В файле header-hooks.php добавляем хук функцией add_action('__before_main_navbar', 'get_theme_buttons')
и записываем код указанной для нашего хука функцией:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | add_action ( '__before_main_navbar', 'get_theme_buttons'); function get_theme_buttons(){ ?> <div class="theme-buttons text-white">Theme: <label for="light">Light</label> <input type="radio" name="themeBtn" id="light" value="" checked> <label for="dark">Dark</label> <input type="radio" name="themeBtn" id="dark" value="dark"> </div> <script> let themeMode = localStorage.getItem('themeMode'); if(themeMode) { document.getElementById(themeMode).checked = true; document.body.classList.add(themeMode); } document.querySelectorAll('[name="themeBtn"]').forEach( item => item.addEventListener('click', changeThemeMode)) function changeThemeMode(event){ localStorage.setItem('themeMode', this.id); themeMode = this.id; themeMode=='dark' ? document.body.classList.add('dark'):document.body.classList.remove('dark'); } </script> <?php } |
Что касается реализации переключения тем в css-файлах темы, то проще всего это сделать с помощью css-переменных, которые меняют свой цвет для body.dark
. Стилизовать переключатели вы тоже можете по своему вкусу.
Данный код нужно использовать в файле темы header.php с помощью функции do_action('__before_main_navbar');
, например, так:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <header class="header-wrap header-top"> <div class="header-cta d-flex"> <ul> <li> <a href="mailto:support@gmail.com"><i class="fal fa-envelope"></i> support@gmail.com</a> </li> <li> <a href="tel:+8801700080702"><i class="fal fa-phone"></i> +012 (345) 67 89</a> </li> </ul> <?php do_action('__before_main_navbar'); ?> </div> </header> |
Код вашего файла может отличаться, т.к. он целиком зависит от темы.
В результате добавления кода верхняя часть хедера может поменяться:
Кастомный хук типа filter
Добавление кастомного хук типа filter предполагает использование функций add_filter()
для определения хука и функции-коллбека для него и apply_filters()
для вызова вашего хука для нужного контента. Важным моментом является то, что фильтры возвращают измененный контент, поэтому обязательно возвращать данные в этих функциях, т.е. использовать ключевое слово return
:
1 2 3 4 5 6 7 8 9 10 11 | add_filter( 'mytheme_uppercase_title', 'mytheme_uppercase_callback' ); function mytheme_uppercase_callback( $title ) { return mb_strtoupper ( $title ); } add_filter( 'nav_menu_item_title', 'mytheme_change_nav_item' ); function mytheme_change_nav_item($content){ return apply_filters('mytheme_uppercase_title', $content); } |
Вот, что получилось:
В результате действия фильтра mytheme_uppercase_title
мы меняем текст выводимых ссылок, преобразуя их в верхний регистр. То же самое можно сделать с помощью css-свойства text-transform: uppercase
, но тот же принцип может быть положен для того, чтобы вывести любой другой контент с более сложными изменениями.