Как фильтры и хуки действительно работают в PHP

21

Как фильтры и хуки на самом деле работают в WordPress?

Я спрашиваю о чем-то продвинутом. Как это реализовано в PHP? Например, как он собирает все хуки из разных плагинов и «прикрепляет» их к основным хукам и т. Д.

Аарон Ли
источник
2
Насколько я знаю, в php нет «хуков» или «фильтров», есть функции. В Wordpress есть специальные функции, которые перед их выполнением используют обратный вызов других функций.
Офир Барух
3
@OfirBaruch, я почти уверен, что OP имел в виду их реализацию в WordPress, и не предполагал, что там была какая-то нативная реализация PHP.
Том Оджер

Ответы:

33

обзор

По сути, « Plugin API », который вызывает Filters и Hooks, состоит из следующих функций:

  1. apply_filters()- выполнить
  2. do_action- выполнить
  3. apply_filters_ref_array()- выполнить
  4. do_action_ref_array()- выполнить
  5. add_filter()- добавить в стек
  6. add_action()- добавить в стек

Основные Внутренние

В целом, есть пара глобальных (что еще в мире WordPress):

global $wp_filter, $wp_actions, $wp_current_filter, $merged_filters;

Первый $wp_filter- глобальный, Arrayкоторый содержит все имена фильтров в виде подмассивов. Каждый из этих подмассивов тогда содержит еще больше подмассивов, которые являются обратными вызовами, вызванными в массиве приоритетов.

Краткое описание

Поэтому, когда вызывается функция execute , WordPress ищет в этих глобальных массивах ключи с этим именем. Затем прикрепленные обратные вызовы получают приоритет выполнения после приоритета. Единственное, что происходит заранее - это обратные вызовы, прикрепленные к allфильтру.

Когда вы добавляете обратный вызов с помощью add_actionили add_filter, WordPress сначала вычисляет «уникальный» идентификатор, чтобы не перезаписывать уже присоединенные обратные вызовы.

$idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);

Затем он добавляет ваш обратный вызов в global $wp_filterстек:

$wp_filter[ $tag ][ $priority ][ $idx ] = array(
    'function'      => $function_to_add,
    'accepted_args' => $accepted_args
);

Как вы можете видеть, основным подмассивом является $tag(или имя действия / фильтра), затем все вызывается с определенным приоритетом, а затем в качестве ключа используется «уникальная» строка обратного вызова / идентификатора.

Позже, когда вызывается фильтр - происходит с $tag/ action- / filter-name - в массиве производится поиск и вызывается обратный вызов. Поскольку он используется call_user_func_array, не имеет значения, сколько аргументов приложено. WordPress решает это сам.

foreach ( (array) current( $wp_filter[ $tag ] ) as $the_ )
{
    call_user_func_array(
        $the_['function'], 
        array_slice(
            $args, 
            0, 
            (int) $the_['accepted_args']
        )
    );
}
кайзер
источник
3
не забывайте, что, проходя обратные вызовы, он упорядочивает выполнение нескольких обратных вызовов на одном хуке, используя их «приоритет», который устанавливается (необязательно) с помощью add_action () и apply_filters () и по умолчанию равен 10.
Том Шнек
1
@ TomAuger Пожалуйста, не стесняйтесь добавлять любые дополнительные заметки и изменения к ответу.
Кайзер
5

Хуки включены как в файлы ядра WordPress, так и в некоторые файлы родительских тем. Они позволяют подключать контент в определенном месте в файле.

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

Пример:

add_action('wp_head', 'add_content_to_head');
function add_content_to_head() {
echo 'Your Content';
}

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

Пример:

add_action('genesis_header', 'add_content_to_header');
function add_content_to_header() {
echo 'Your Content';
}

Вот как выглядит ловушка, если вы открыли файл header.php в каркасе темы Genesis:

do_action( 'genesis_header' );

Вот список хуков WordPress, которые вы можете использовать разными способами.

Фильтры позволяют изменять выходные данные существующей функции и включены как в основные файлы WordPress, так и в некоторые каркасы родительских тем, такие как Genesis.

Вот список фильтров, которые вы можете использовать с Genesis Design Framework

Вот список фильтров, включенных в WordPress

Вот пример того, как вы можете использовать фильтр в рамках темы, такой как Genesis:

add_filter( 'comment_author_says_text', 'custom_comment_author_says_text' );
function custom_comment_author_says_text() {
return 'author says';
}

Приведенный выше код можно использовать в дочерней теме, чтобы изменить текст автора в комментариях. Работает в любой теме.

Вот еще один пример, который настраивает длину выдержки до 50 слов:

add_filter( 'excerpt_length', 'change_excerpt_length' );
function change_excerpt_length($length) {
return 50; 
}

Вы найдете функцию the_excerpt () в файле wp-includes / post-template.php.

Вот как это выглядит:

  function the_excerpt() {
        echo apply_filters('the_excerpt', get_the_excerpt());
}

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

По сути, хуки и фильтры позволяют настраивать и изменять как WordPress, так и вашу родительскую тему, не редактируя основные файлы WordPress или файлы родительских тем.

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

Брэд Далтон
источник
2
Это отличный общий обзор хуков и фильтров, но я боюсь, что полностью пропускает вопрос ОП, касающийся внутренних аспектов работы хуков и того, как WordPress создает, хранит и обрабатывает их. Отличный ответ; Вы, вероятно, должны дать ссылку на свой учебник на сайтах WP.
Том Оджер
Хорошо, я удалю это. Мое плохое, поскольку я должен был прочитать вопрос лучше, но думал, что уже даные ответы было бы легче понять новичкам, если бы они сначала знали основы.
Брэд Далтон
2
Брэд, я удалил его, так как думаю, что здесь тоже может быть полезна эта информация. Если вы не согласны, просто упомяните / пингуйте меня здесь, и я удалю его снова.
Кайзер