Статьи

Reel ’em In: Понимание крючков изнутри

Ключом к гибкой основе WordPress является использование хуков. Будь то темы, плагины или ядро, хуки обеспечивают беспрецедентный рост и обеспечивают совместимость с будущими версиями WordPress. В результате, понимание их, несомненно, должно быть частью репертуара любого разработчика. Присоединяйтесь, чтобы раскрыть тонкости этой простой, но сложной системы изнутри.

В качестве дорожной карты для этой статьи мы рассмотрим концепцию хуков, их реализацию и, конечно, примеры.


Крючки

«Проще говоря, крюк является заполнителем для действия».

За любым хорошо написанным программным обеспечением лежит надежная концепция, которая отвечает на вопросы о том, что и почему. Крючки не являются исключением. Проще говоря, крюк является заполнителем для действия. Когда происходит значительное событие, такое как публикация сообщения, активируется хук, позволяющий происходить соответствующим реакциям. С точки зрения разработчика, можно рассматривать хуки как реализацию системы, управляемой событиями.

Больше, чем просто определение, концепция требует аргументации — поддержки, объясняющей, почему она полезна. Крючки играют неотъемлемую роль в WordPress из-за постоянно меняющейся природы проекта. Сотни разработчиков постоянно обновляют систему, поэтому невозможно редактировать основные файлы для каждого плагина, темы или специальной настройки, поскольку они часто меняются. Вместо этого необходима структура для расширения системы, чтобы внешние функции имели такой же эффект, как и внутренние манипуляции. Крючки являются ключом к этой структуре.


Как разработчик, его роль расширяется, чтобы не только понять, что что-то делает или почему это делается, но также и понять, как это создается. Другими словами, чтобы полностью понять систему хуков, нужно понять, как они реализованы.

Однако, как и в тесте с множественным выбором, смотреть на ответы сначала не обязательно лучшая идея. Как подсказывают многие стратегии сдачи тестов, часто лучше прочитать вопрос, сформулировать свои собственные мысли об ответе, а затем выбрать вариант, наиболее близкий к вашему рассуждению. Подобный метод может быть применен при понимании реализаций разработки программного обеспечения; вместо того, чтобы смотреть на чужой код, чтобы понять, как реализована функция, часто еще более полезно сначала реализовать ее самостоятельно, а затем вернуться, чтобы проверить, как это делается на самом деле. Это именно то, что мы будем делать.

Вместо того, чтобы смотреть на чужой код, чтобы понять, как реализована функция, часто еще более полезно сначала реализовать ее самостоятельно, а затем вернуться, чтобы проверить, как это делается на самом деле.

Чтобы получить представление о том, как реализована система, часто полезно начать с документации. Давайте рассмотрим резюме двух основных функций ловушки WordPress в соответствии с Кодексом :

  • add_action( $hook, $function [, $priority [, $numArgs ] ] ) — Определяет обработчик $function , который будет вызываться при активации определенного крючка $hook из-за возникновения события. $priority определяет, вызывается ли этот обработчик функции до или после других обработчиков функций, и по умолчанию равен 10. Низкие приоритеты приводят к вызову функции раньше и наоборот. $numArgs — это число аргументов, которые обработчик функции примет и по умолчанию равно 1.
  • do_action( $hook [, $arg1 [, $arg2 [, $arg3 [, ... ] ] ] ] ) — активирует определенный хук, $hook , вызывая все функции обработки с необязательными аргументами $arg1 , $arg2 , $arg3 и т. д.

Имея документацию в руках, пришло время сделать некоторые выводы об этих двух функциях. add_action просто нужно связать функцию, приоритет и количество аргументов со строкой. Это похоже на идеальную работу для массива PHP, который двойным образом действует как хэш-карта, в которой хранятся пары ключ-значение. do_action еще более тривиален, требует простого просмотра этого же массива для поиска соответствующих обработчиков функций и последующего их вызова. Учитывая наше понимание, пришло время перейти к нашей реализации.

Знание

Поскольку мы делаем это, чтобы получить представление о системе ловушек WordPress, нет необходимости реализовывать эти две функции дословно из документации. Вместо этого давайте сконцентрируемся на их реализациях без необязательных аргументов, чтобы сэкономить время и все же понять суть.

Прежде чем мы начнем, давайте выложим схему:

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

Это дает следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$actions = array();
 
function add_action( $hook, $function )
{
    global $actions;
 
    // create an array of function handlers if it doesn’t already exist
    if( !isset( $actions[ $hook ] ) )
        $actions[ $hook ] = array();
 
    // append the current function to the list of function handlers
    $actions[ $hook ][] = $function;
}
 
function do_action( $hook )
{
    global $actions;
 
    if( isset( $actions[ $hook ] ) )
    {
        // call each function handler associated with this hook
        foreach( $actions[ $hook ] as $function )
            call_user_func( $function );
    }
}

Это неплохо; мы внедрили универсальную систему хуков примерно в 20 строк кода. Теперь, когда мы получили представление о том, как работают хуки, давайте углубимся в основной код WordPress, чтобы подтвердить нашу гипотезу.

Инструментом для быстрой навигации по этому коду является перекрестная ссылка Yoast на источник WordPress . Поиск add_action приводит к следующему коду:

01
02
03
04
05
06
07
08
09
10
11
12
function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
    return add_filter($tag, $function_to_add, $priority, $accepted_args);
}
 
function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
    global $wp_filter, $merged_filters;
 
    $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
    $wp_filter[$tag][$priority][$idx] = array(‘function’ => $function_to_add, ‘accepted_args’ => $accepted_args);
    unset( $merged_filters[ $tag ] );
    return true;
}

add_action вызывает add_filter который, что неудивительно, добавляет данную функцию в массив с ключом имени $tag . Несмотря на то, что из-за параметров $priority и $accepted_args задействовано немного больше, эта функция по существу согласуется с нашей собственной, подтверждая наши подозрения. do_action , хотя и более длинный и чуть более сложный, сводится к следующему коду:

01
02
03
04
05
06
07
08
09
10
11
12
function do_action($tag, $arg = ») {
    [Omitted code that records statistics, processes arguments, and deals with filters]
 
    do {
        foreach ( (array) current($wp_filter[$tag]) as $the_ )
            if ( !is_null($the_[‘function’]) )
                call_user_func_array($the_[‘function’], array_slice($args, 0, (int) $the_[‘accepted_args’]));
 
    } while ( next($wp_filter[$tag]) !== false );
 
    [Omitted code that cleans up]
}

Цикл по связанным функциям и вызов каждой из них не являются странными для всех нас; на самом деле, это именно то, что мы предположили в нашей реализации. Следовательно, начинание с собственных мыслей о коде не только помогло нам лучше понять его, но и потребовало критического мышления и решения проблем, которые необходимы для разработки программного обеспечения.


С нашим пониманием того, что, почему и насколько хорошо, пришло время перейти к двум примерам. Первый — это игра в формате RSS; вместо того, чтобы предоставлять уведомления через синдикацию, почему бы не использовать электронную почту вместо этого?

Эл. почта

Чтобы внедрить нашу систему, нам нужно искать, когда публикация публикуется. Но какой крюк мы должны использовать? Справочник действий API предоставляет список хуков вместе с описаниями связанных событий, которые могут помочь нам точно идентифицировать это. Действительно, publish_post ловушки publish_post соответствует тому, что нам нужно, поэтому давайте добавим к нему обработчик функции:

1
add_action( ‘publish_post’, ‘notify_via_email’ );

notify_via_email отправить уведомление по электронной почте кому-нибудь в notify_via_email функции notify_via_email . Обратите внимание, что ссылка на действие API указывает, что publish_post передает идентификатор сообщения в качестве аргумента нашей функции обработки. Это позволит нам получить информацию о записи через функцию get_post , например:

1
2
3
4
5
6
7
8
9
function notify_via_email( $post_id ) {
    $post = get_post( $post_id );
    $to = ‘[email protected]’;
 
    $subject = ‘Post Published on ‘ .
    $message = $post->post_title .
 
    wp_mail( $to, $subject, $message );
}

После получения сообщения мы используем его название, дату и постоянную ссылку в нашем сообщении электронной почты. Затем он отправляется через функцию wp_mail , для которой в качестве параметров требуются получатель, тема и сообщение. На этом наша простая система уведомлений по электронной почте завершена. Обратите внимание, что не рекомендуется вызывать wp_mail несколько раз одновременно, так как это неизбежно приводит к значительной задержке времени загрузки страницы после нажатия кнопки публикации публикации.

аналитика

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

Хотя наше первое приложение было немного надуманным, мы познакомились с использованием хуков. Этот второй пример, однако, пригодится для реального использования. Мы создадим простой плагин Google Analytics, который автоматически вставит код отслеживания в нижний колонтитул страницы.

Сначала может показаться, что тема является более подходящим средством для такого кода. Наоборот, тема сайта подвержена пересмотру и изменению. В результате код аналитики может легко потеряться при переходе от одной темы к другой. Создание плагина обходит этот недостаток; поскольку он останется активным независимо от того, какая тема используется, аналитический код все равно будет присутствовать и устранит необходимость в обслуживании темы.

Но как мы вставляем код в нижний колонтитул сайта? Это тоже делается с помощью хуков. Если вы работали над темами WordPress ранее, вы, вероятно, вызывали функции wp_head и wp_footer в wp_footer и нижнем колонтитулах вашего сайта соответственно. Обе эти функции присутствуют для простой активации хуков, чтобы плагины могли легко вставлять код в эти важные области страницы. Следовательно, мы просто добавим действие в хук wp_footer :

1
add_action( ‘wp_footer’, ‘add_google_analytics_code’ );

Наша функция add_google_analytics_code , как следует из названия, печатает код Google Analytics:

1
2
3
4
5
6
7
8
<?php function add_google_analytics_code() { ?>
<script>
    var _gaq=[[‘_setAccount’,’UA-XXXXX-X’],[‘_trackPageview’]];
    (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
    g.async=g.src=’//www.google-analytics.com/ga.js’;
    s.parentNode.insertBefore(g,s)}(document,’script’))
</script>
<?php } ?>

Не забудьте сменить UA-XXXXX-X на идентификатор вашего сайта, и все готово! Просто добавьте этот код в файл и загрузите его в каталог плагинов WordPress. Обязательно вставьте заголовок плагина, вот так:

01
02
03
04
05
06
07
08
09
10
11
<?php
/*
Plugin Name: Wptuts+ Google Analytics Plugin
Plugin URI: [Insert a link to this article.]
Description: This plugin adds Google Analytics tracking code to the footer of a WordPress site.
Version: 1.0
Author: Your Name
Author URI: http://example.org
License: GPL2
*/
?>

Не забудьте изменить имя автора, URI автора и, конечно же, активировать плагин!


Разделив хуки на концепцию, реализацию и примеры, мы эффективно изучили их изнутри ядра WordPress наружу в реальном приложении. Вместо того, чтобы просто смотреть на код ядра WordPress, мы реализовали нашу собственную версию хуков путем логического вывода, что позволило нам получить более глубокое, похожее на разработчика понимание этой мощной системы. Наконец, с помощью реального приложения Google Analytics Plugin мы получили предварительное представление о том, насколько полезными могут быть хуки. Обязательно присоединяйтесь к нам в следующий раз и не стесняйтесь делиться своими собственными, инновационными способами использования хуков в комментариях ниже!