Если вы плохо знакомы с хуками, эта статья поможет вам. Приведенные в статье примеры взяты из ядра WordPress, а также из собственного многолетнего опыта работы разработчиком плагинов.
Хуки WordPress — это функция, которая позволяет расширять возможности плагины и темы без риска их сломать. Что такое хуки?
Хук «do» называется «действием». В любом месте, где определено действие, можно выполнить собственный код. Вот некоторые примеры:
- отправить электронное письмо автору после публикации записи;
- загрузить пользовательский скрипт в футере страницы;
- добавить инструкции над формой входа.
Хук «customize» называется «фильтром». Фильтр позволяет изменять или настраивать значение и возвращать его в новой форме. Вот некоторые примеры:
- вывод заголовков записей заглавными буквами;
- прикрепление ссылки к связанным записям ниже основного контента;
- изменение параметра, который извлекается из базы данных.
Для фильтра важна не только позиция, но и возвращаемые значения. WordPress имеет фильтр почти для каждого значения, которое обрабатывает.
Элементы процедуры хукаИспользуем в качестве примера действия хук wp_head , а в качестве примера фильтра хук the_content .
Хук (существительное)Сам хук — это указание того, когда и где происходит магия. Представьте себе, что это крюк, который альпинист вбил в поверхность скалы. Крюк имеет определенную позицию. Если другие альпинисты захотят двигаться в этом направлении, они могут использовать его.
Хуки действий вызываются с помощью функции do_action:
do_action("wp_head");
Хуки вызываются с помощью apply_filters() :
$content=apply_filters("the_content",$content);
Как видите, нам нужно перехватить данные из фильтра.
Действия и фильтрыСледующий элемент в процедуре хука — это действие или фильтр. Это функция, которую вы определяете, чтобы сделать или отфильтровать что-то. Это альпинист, который готов использовать любой крюк, чтобы взобраться немного выше.
Действие, которое запускается в wp_head
— это noindex()
.
functionnoindex(){ // Если блог не является публичным, указать роботам проходить мимо. if("0"==get_option("blog_public")) wp_no_robots(); }
Хук проверяет, отключена ли настройка видимости для поисковых систем. Если это так, wp_no_robots()
добавляет мета тег robots
, указывающий поисковым системам не индексировать сайт.
Примером фильтра для the_content
является wpautop()
. Он отвечает за перенос абзацев в теге
И использование тега
для разрывов строк.
functionwpautop($pee,$br=true){ // … return$pee; }
В отличие от действия, функции фильтра требуется хотя бы один аргумент. Он должен быть возвращен.
Хук (глагол)В процедуре хука WordPress нужно указать, для чего именно предназначен хук. Это означает, что мы должны привязать функцию (глагол) к крюку (существительному). Это делается с помощью функции, которая часто неправильно называется «хуком».
Для хука wp_head
и действия noindex()
связь устанавливается с помощью этой строки кода:
add_action("wp_head","noindex",1);
Третий параметр является приоритетом. Мы рассмотрим его ниже.
Включение wpautop()
в the_contentо
осуществляется с помощью этой строки:
add_filter("the_content","wpautop");
Это основные принципы процедуры хука. В следующих разделах мы рассмотрим их более подробно.
Вы уже используете эти хукиДаже если вы «просто» изменяете тему или добавляете код в файл functions.php , вы уже используете действия и фильтры.
WP_HEADРассмотрим раздел заголовка темы Twenty Fifteen, который можно найти в файле wp-content/themes/twentyfifteen/header.php .
Между открывающимся и закрывающимся тегами
размещается не так уж много кода, но просмотрите исходный код страницы в браузере. Вы увидите там различные мета элементы, включая тег
.
Элементы, которые могут отсутствовать в файле header.php
, добавляются функцией wp_head()
. Если вы используете среду разработки, просмотрите ее содержимое.
/** * Запуск действия wp_head * * @since 1.2.0 */ functionwp_head(){ /** * Выводим через front-end скрипт или данные в теге head. * * @since 1.5.0 */ do_action("wp_head"); }
Единственное, что делает функция wp_head()
, это выводит хук wp_head
. Это означает, что тема может использовать do_action(‘wp_head’)
, вместо wp_head ()
.
Этот хук уже используется ядром. Вот некоторые действия, которые WordPress подключает к этому хуку по умолчанию:
add_action("wp_head","_wp_render_title_tag",1); add_action("wp_head","wp_enqueue_scripts",1); add_action("wp_head","feed_links",2); add_action("wp_head","feed_links_extra",3); add_action("wp_head","rsd_link"); add_action("wp_head","wlwmanifest_link"); add_action("wp_head","adjacent_posts_rel_link_wp_head",10,0); add_action("wp_head","locale_stylesheet"); add_action("wp_head","noindex",1); add_action("wp_head","print_emoji_detection_script",7); add_action("wp_head","wp_print_styles",8); add_action("wp_head","wp_print_head_scripts",9); add_action("wp_head","wp_generator"); add_action("wp_head","rel_canonical"); add_action("wp_head","wp_shortlink_wp_head",10,0); add_action("wp_head","wp_site_icon",99);
Среди них — действие noindex() , а также (начиная с версии WordPress 4.1) вызов _wp_render_title_tag() , который генерирует тег title .
КонтентПример хука фильтра, который вы использовали, даже не зная об этом — the_content
.
Он скрыт за функцией the_content()
, которая используется для вывода содержимого записи или страницы. Она содержит вызов хука the_content
.
functionthe_content($more_link_text=null,$strip_teaser=false){ $content=get_the_content($more_link_text,$strip_teaser); // … $content=apply_filters("the_content",$content); $content=str_replace("]]>","]]>",$content); echo$content; }
По умолчанию к функции the_content уже подключено несколько фильтров.
add_filter("the_content","wptexturize"); add_filter("the_content","convert_smilies"); add_filter("the_content","convert_chars"); add_filter("the_content","wpautop"); add_filter("the_content","shortcode_unautop"); add_filter("the_content","prepend_attachment");
Эти фильтры отвечают за формат и ряд специальных символов в тексте. Они также широко используется плагинами для присоединения таких элементов, как иконки социальных сетей или связанных записей.
Уроки использования the_contentВот два примера того, как неправильное использование хука приводит к сбою в работе функции.
Тело функции the_content()
также содержит вызов get_the_content()
. Я видел, как второй использовался вместо первого в нескольких темах. Но таким образом сам хук отключается, и многие функции не будут работать.
Если вы подключаетесь к the_content
, то имейте в виду, что он используется не только на страницах контента, но и на страницах списков. Например, в архивах, а также на главной странице.
Основные параметры, которые нужны — это имя хука, имя функции, приоритет и аргументы, которые ей передаются.
Вот как выглядит вызов add_filter
:
add_filter($tag,$function,$priority,$accepted_args);
Имена хуков ($teg)Вы не сможете ничего сделать с именами хуков, которые используются в ядре WordPress, плагинах или темах оформления. Но при задании собственных имен нужно придерживаться нескольких принципов.
Имя действия должно включать в себя место, а фильтр-место и значение, которое будет изменено.
В качестве примеров действий можно привести wp_head
и wp_footer
, которые называются в соответствии с местом их расположения. Также часто используются префиксы или суффиксы. Например: before
, pre
, begin
, after
и end
.
Функция wp_delete_post() , которая отвечает за удаление записи, включает в себя следующие хуки:
- before_delete_post;
- delete_post;
- deleted_post;
- after_delete_post.
Помимо позиции и значения нужно задать префикс хука префикса. Например:
- wpseo_ от Yoast SEO;
- genesis_ от фреймворка Genesis;
- advanced_ads_ от моего плагина Advanced Ads.
Это предотвращает конфликты с хуками в других плагинах или темах оформления.
Динамические имена хуковПредположим, что в плагине есть много параметров, и вы хотите, чтобы другие разработчики могли использовать фильтр для каждого из них. Для этого нужно вызывать apply_filters() для каждого параметра. Также можно использовать динамическое имя хука, как это делает WordPress в функции get_options() .
Данная функция включает в себя следующие хуки:
- ‘pre_option_’ . $option;
- ‘default_option_’ . $option;
- ‘option_’ . $option.
Зная это, вы сможете подключиться к option_blogname или option_blogdescription , чтобы динамически изменять название или описание блога.
Магический «all»При вызове add_action() и add_filter() в качестве имени хука можно использовать специальный тег. Благодаря чему связанная функция будет использоваться для каждого хука.
Имена функцийПри вызове простой функции добавляйте префикс. Это предотвратит конфликты с другими вспомогательными функциями, которые идентифицируют его.
На форумах можно встретить имена функций, начинающиеся с my_
. Измените этот префикс на свой.
add_filter("the_content","bestpluginever_capitalize_all_words");
Также возможно подключение статичной функции в классе:
add_filter("the_content",array("bestpluginever","capitalize_all_words"));
Ее вызов в экземпляре этого класса будет выглядеть следующим образом:
add_filter("the_content",array($bestpluginever,"capitalize_all_words"));
Также можно вызвать метод в экземпляре того же класса, например:
add_filter("the_content",array($this,"capitalize_all_words"));
Также убедитесь, что функции являются public .
Использование PHP функций по умолчаниюВ определенных случаях не нужно создавать собственную функцию. Эта процедура хука преобразует в заглавную каждую первую букву заголовка записи:
functionbestpluginever_capitalize_title($title){ returnucwords($title); } add_filter("the_title","bestpluginever_capitalize_title");
Поскольку ucwords() является стандартной функцией PHP, которая принимает и возвращает значение, ее можно сократить до одной строки:
add_filter("the_title","ucwords");
ПриоритетыТретий параметр в add_action()
и add_filter()
— это приоритет. Он устанавливает порядок, в котором вызываются функции, связанные с хуком.
Этот параметр является необязательным и по умолчанию равен 10, если не определен явно. Несколько функций с одинаковым приоритетом будут вызываться в том порядке, в котором они были зарегистрированы в хуке.
Плагин Advanced Ads использует the_content
при вставке рекламных объявлений до или после контента. Ее третий параметр определяет, вставляется ли сначала рекламное объявление или другой контент. Чтобы избежать обращений за поддержкой относительно «неправильного» порядка элементов, я предоставил пользователям возможность выбирать приоритет фильтра в качестве опции.
Чтобы проверить, выполнено ли конкретное действие, можно использовать did_action()
.
Функция _wp_render_title_tag
была подключена к wp_head
. Это пример того, как ядро Wordpress проверяет, что тег title
действительно создан только тут.
function_wp_render_title_tag(){ if(!current_theme_supports("title-tag")){ return; } // Это может работать только внутри wp_head. if(!did_action("wp_head")&&!doing_action("wp_head")){ return; } echo"".wp_title("|",false,"right")."n"; }
did_action($hook)
возвращает информацию о том, сколько раз было выполнено действие, включая текущий вызов. Функция вернет 1, если _wp_render_title_tag()
запускается в wp_head
. do_action(‘wp_head’)
проверяет, находимся ли мы сейчас в действии wp_head
. Фактически, приведенный выше код — это двойная проверка. Из-за этого он будет удален из WordPress 4.4.0.
Функция do_action()
проверяет, действительно ли происходит действие.
Для фильтров did_action()
и do_action()
нет псевдонимов. Вместо них нужно использовать has_filter($hook, $function)
. Когда указан только $hook,
будет возвращено значение true
, если какая-либо функция зарегистрирована для hook. Значение false
— в противном случае.
Если также передана функция $function
, то будет возвращен приоритет этой функции, или значение false
, если эта функция не подключена к хуку.
При добавлении рекламных объявлений после определенного абзаца плагин Advanced Ads должен убедиться, что wpautop()
вызывается до того, как будет применена пользовательская функция фильтра.
$wpautop_priority=has_filter("the_content","wpautop"); if($wpautop_priority&&$advads_content_injection_priority()update , где обновляю таблицу с балами конкретного пользователя. В уроке , я рассказывал о классе $wpdb->insert на основе которого вы можете сделать свою функцию с использованием $wpdb->update, данный класс работает аналогичным образом.
Вот как примерно выглядит конструкция с использованием хука:
Function add_point() { //Тут функция } add_action("publish_post", "add_point");
Все что внутри функции, будет срабатывать при публикации поста. Вы можете использовать любой другой хук , который есть на сайте WordPress.
Вот функция с обновлением баллов:
Function add_point() { global $wpdb; $user_ID = get_current_user_id(); $result = $wpdb->get_results("SELECT points FROM user_points WHERE user = "".$user_ID."""); $update = $result->points + 10; $wpdb->update("user_points", array("points" => $update,), array("user" => $user_ID), array("%d",), array("%d")); } add_action("publish_post", "add_point");
Данная функция не закончена, я ее показал для наглядности, чтобы было понятно, как можно работать с хуками и функциями.
Одним из краеугольных камней выполнения задач в WordPress является понимание принципов работы хуков (зацепок). Само по себе это не сложно, а в этой статье мы постараемся ознакомить вас с основами.
Но даже если вы хотите получить более глубокие познания, то вам всё-равно необходимо знать, как применять хуки.
Мы расскажем вам о системе хуков WordPress и их использовании, а также рассмотрим хуки действия и фильтров.
Перед тем, как начать, убедитесь, что вы имеете всё необходимое для работы, и у вас установлена последняя версия WordPress.
Что такое хуки?До того, как мы рассмотрим WordPress хуки, необходимо понять событийно-ориентированную архитектуру разработки.
Если вы работали с уже существующими хуками WordPress, или с фронтенд веб-разработкой, или с JavaScript, то вы, скорее всего, знакомы с этим понятием, даже если не знали, что у него есть официальное название.
Архитектура, управляемая событиями (англ. event-driven architecture, EDA) является шаблоном архитектуры программного обеспечения, позволяющим создание, определение, потребление и реакцию на события.
Если вы только начали работать с шаблонами проектов или разработкой, то это может показаться вам сложным, но лучше воспринимать это так:
- Программное обеспечение в определенные моменты может присылать вам сообщение о каком-то событии.
- Мы, как разработчики, способны написать код, который отслеживает эти сообщения, а потом отвечает на них пользовательским кодом.
Обратите внимание, что в определении речь идёт и о создании событий. Когда мы будем обсуждать наши собственные хуки, то вернёмся к этой теме. А теперь давайте рассмотрим два события, распространённых в веб-разработке.
Использование JavaScriptПредставьте, что вы работаете в сфере фронтенд разработки. У вас есть кнопка с ID атрибутом command-button , и когда пользователь нажимает на неё, то должно открыться диалоговое окно.
С помощью jQuery вы можете реализовать этот функционал вот так:
(function($) { "use strict"; // jQuery"s DOM-ready event-handler $(function() { /** * Listen for the "click" event on the button identified * with the "command-button" ID attribute. * * When the user clicks on it, display an alert dialog. */ $("#command-button").bind("click", function(evt) { alert("You clicked the button."); }); }); })(jQuery);
Комментарии в коде объясняют принцип работы. Короче говоря, браузер воспроизводит событие, когда пользователь нажимает на кнопку. Когда это происходит, наш код отслеживает события, а потом отвечает, выводя на экран диалоговое окно.
Конечно, другие библиотеки, платформы или vanilla JavaScript предлагают тот же самый набор функций. Причиной, почему мы рассказываем о jQuery, является то, что это одна из самых распространённых библиотек JavaScript, и потому что она связана с WordPress.
Использование WordPressПрименение этого шаблона разнится в зависимости от языка программирования или парадигмы. Это часто зависит от API, который предоставляет платформа или приложение.
В WordPress регистрация собственного кода, запускающего события, немного отличается. К примеру, давайте представим, что вы работаете с административной страницей в WordPress и хотите добавить новый элемент подменю в меню Настройки . Назовём его Tuts+ Options .
Для этого мы добавляем следующий код в файл functions.php , или в плагин, или в любой тип проекта, с которым мы работаем: