Разработка

Действия и фильтры в WordPress – в чём разница?

WordPress
Действия и фильтры в WordPress

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

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

Дефиниции и различия

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

Функции

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

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

Позже мы рассмотрим различные пути исполнения функций.

Хуки действий

Хуки действий (или действия) вызываются тогда, когда что-то происходит, например загрузка страницы, авторизация пользователя или кастомное действие, которое вы определяете в вашей теме или плагине.

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

Хуки фильтров

Хуки фильтров (или фильтры) контролируют то, как что-то случится или изменяют что-то, что уже было выведено. Вы можете использовать фильтр для вывода мета-данных в определённом формате, для переопределения текста или полностью предотвратить что-то от показа.

В коде вы добавляете фильтры через функцию apply_filters(). Мы вернёмся к ней чуть позже. Слово apply как раз показывает, что вы применяете фильтры к текущему коду, в то время как действия, которые вы создаёте через do_action() пусты, пока вы не привяжете к ним функции.

Использование функций, действий и фильтров

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

Вызов функций напрямую

Ниже пример функции, которая вызывается напрямую в файле шаблона. Это простой вывод информации в футер:

if ( ! function_exists( 'compass_colophon' ) ) {
function compass_colophon() { ?>
    <section class="colophon" role="contentinfo">
        <small class="copyright left">
            <?php echo compass_copyright(); ?>
            <a href="/<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
            <?php bloginfo( 'name' ); ?>
            </a>
        </small><!-- #copyright -->
 
        <small class="credits right">
                Powered by <a href="http://wordpress.org/">WordPress</a> and designed by <a href="http://compass-design.co.uk">Compass Design</a>.
            </a>
        </small><!-- #credits -->
    </section><!--#colophon-->
    <?php }
}

Если использовать функцию в родительской теме, а потом создать новую функцию с таким же именем в дочерней теме, то она переопределит эту функцию. Обратите внимание, что функция включает в себя другую функцию compass_copyright().

Эта функция находится в файле functions.php родительской темы. Мы можем вызвать её напрямую в файле footer.php темы:

compass_colophon();

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

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

Привязка функций к действиям

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

Создание хуков действия

Итак, вместо вызова compass_colophon() в файле footer.php мы можем добавить хук действия:

do_action( 'compass_in_footer' );

Функция do_action() принимает один обязательный параметр – название действия. Вы также можете добавлять необязательные аргументы.

Привязка функций к действиям

Теперь вместо вызова функции мы должны привязать её к нашему новому хуку действия. В файле functions.php добавляем:

add_action( 'compass_in_footer', 'compass_colophon');

Этот код привязывает нашу функцию к действию compass_in_footer. Это означает, что код нашей функции будет вызван в той точке кода, где будет размещено действие. Первый параметр – это имя хука действия, а второй параметр – это имя нашей функции.

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

Скажем, у нас есть другая функция compass_smallprint(), которую мы хотим привязать к хуку compass_in_footer. Вот она:

if ( ! function_exists( compass_smallprint() ) ) {
    function compass_smallprint() {
        // contents of function here
    }
}
add_action( 'compass_in_footer', 'compass_smallprint', 20 );

Привязываем её к действию:

add_action( 'compass_in_footer', 'compass_smallprint', 20 );

Вы видите, что третьим параметром был установлен приоритет. Приоритет по умолчанию – 10. Он будет применён, если третий параметр не указан. Так как мы не устанавливали приоритет для функции compass_colophon(), установка 20 для compass_smallprint() заставит выполниться эту функцию после функции compass_colophon().

Отвязка функций от действий

Иногда нужно отключить функцию от выполнения, и мы не можем сделать это через переопределение. Если функция была привязана к хуку действия, то мы можем сделать это через функцию remove_action().

Например, если мы хотим отключить compass_smallprint(), то мы отвязываем её от действия compass_in_footer:

remove_action( 'compass_in_footer', 'compass_smallprint', 20 );

У функции remove_action() три параметра: имя хука действия, имя функции и приоритет, с которым функция была изначально привязана к действию. Чтобы это сработало, необходимо обязательно указать приоритет.

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

Для отвязки всех функций используйте функцию remove_all_actions():

remove_all_actions( 'compass_in_footer');

Если вторым параметром мы передадим приоритет, то будут удалены только те функции, которые были привязаны к действию с этим приоритетом.

Привязка функций к фильтрам

У нас также есть возможность привязывать наши функции к хукам фильтров. Мы делаем это для изменения или переопределения существующего кода. Когда вы создаёте хук фильтра (с помощью функции apply_filters()), вы оборачиваете его вокруг кода вашей темы или плагина, который потом изменяется любым фильтром, который привязан к этому хуку.

Это может быть полезно, если у нас есть опции темы или плагина, которые мы хотим переопределить. Или мы создаём родительскую тему, в которой могут быть элементы, которые могут быть переопределены в дочерней теме.

Создание хуков фильтра

У функции apply_filters() три параметра: имя хука фильтра, значение, которое мы хотим отфильтровать (например значение по умолчанию), а также необязательные переменные, которые мы передаём в функции, привязанные к фильтру.

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

Возвращаясь к нашей функции compass_colophon(), мы переделаем её в фильтр, добавляя её содержимое в файл footer.php внутри функции apply_filters():

echo apply_filters( 'compass_colophon', '
    <section class="colophon" role="contentinfo">
        <small class="copyright left">
            <?php echo compass_copyright(); ?>
            <a href="/<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
            <?php bloginfo( 'name' ); ?>
            </a>
        </small><!-- #copyright -->
 
        <small class="credits right">
                Powered by <a href="http://wordpress.org/">WordPress</a> and designed by <a href="http://compass-design.co.uk">Compass Design</a>.
            </a>
        </small><!-- #credits -->
    </section><!--#colophon-->'
);

Это выведет код, который мы установили во втором параметре функции apply_filters().

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

Поэтому мы добавляем действие compass_in_footer в файл footer.php при помощи функции do_action(), а потом создаём функцию в файле functions.php, которая привязана к этому действию и содержит фильтр:

if ( ! function_exists( 'compass_colophon' ) ) {
function compass_colophon() {
    echo apply_filters( 'compass_colophon_filter', '
        <section class="colophon" role="contentinfo">
            <small class="copyright left">
                <?php echo compass_copyright(); ?>
                <a href="/<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
                <?php bloginfo( 'name' ); ?>
                </a>
            </small><!-- #copyright -->
     
            <small class="credits right">
                    Powered by <a href="http://wordpress.org/">WordPress</a> and designed by <a href="http://compass-design.co.uk">Compass Design</a>.
                </a>
            </small><!-- #credits -->
        </section><!--#colophon-->'
    );
}
add_action( 'compass_in_footer', 'compass_colophon' );

Это означает, что мы теперь можем переопределить контент по умолчанию, используя три разных варианта:

  • Создать новую функцию compass_colophon() в дочерней теме, которая переопределит функцию родительской темы
  • Отвязать функцию compass_colophon() от хука действия compass_in_footer и написать новую функцию, которую привязываем к хуку в нужном месте
  • Создать новую функцию и привязать её к хуку фильтра compass_colophon_filter, который переопределит значение в функции apply_filters()

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

Так что можно создать два фильтра, один для раздела copyright, а второй для credits:

if ( ! function_exists( 'compass_colophon' ) ) {
function compass_colophon() {
     
    echo '<section class="colophon" role="contentinfo">';
         
        echo apply_filters( 'compass_copyright_filter', '
            <small class="copyright left">
                <?php echo compass_copyright(); ?>
                <a href="/<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
                <?php bloginfo( 'name' ); ?>
                </a>
            </small><!-- #copyright -->'
        );
         
        echo apply_filters( 'compass_copyright_filter', '
            <small class="credits right">
                    Powered by <a href="http://wordpress.org/">WordPress</a> and designed by <a href="http://compass-design.co.uk">Compass Design</a>.
                </a>
            </small><!-- #credits -->'
        );
    echo '</section><!--#colophon-->';
}
add_action( 'compass_in_footer', 'compass_colophon' );

Таким образом мы можем переопределить всю функцию compass_colophon отвязав её или написав новую функцию в дочерней теме. Либо мы можем создать функцию, которая будет привязана к хукам фильтра compass_copyright_filter или compass_credits_filter, что позволит переопределить каждый элемент отдельно.

Привязка функций к фильтрам

Для привязки функции к хуку фильтра, мы используем функцию add_filter(), которая принимает два параметра: имя хука и имя функции.

Для изменения credits мы могли бы написать такую функцию:

function new_credits() { ?>
    <small class="credits right">
        Powered by <a href="http://wordpress.org/">WordPress</a> and designed by <a href="http://rachelmccollin.co.uk">Rachel McCollin</a>.
            </a>
    </small><!-- #credits -->
<?php }
add_filter( 'compass_credits_filter', 'new_credits' );

Это переопределяет значения, изначально установленные в хуке фильтра compass_credits_filter, значением из новой функции new_credits(), но при этом оставляет нетронутым всё остальное в функции compass_colophon().

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

Отвязка функци от фильтров

Так же как и с хуками действий, вы можете удалять функции из хуков фильтров. Делается это при помощи функции remove_filter(), которая принимает три параметра: имя фильтра, имя функции и приоритет.

Например, для удаления new_credits() мы используем следующий код:

remove_filter( 'compass_credits_filter', 'new_credits');

Таким образом код откатится к значению, которое мы указали в оригинальной функции apply_filters(). Если мы хотим удалить функцию new_credits(), и вместо неё ничего не выводить, то нам необходимо добавить новую функцию. Далее мы отвязываем первую функцию и привязываем новую:

function no_credits() {
    return;
}
remove_filter( 'compass_credits_filter', 'new_credits' );
add_filter( 'compass_credits_filter', 'no_credits' );

Итоги

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

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

Оригинальная статья:
Dmitry Rekun
Работаю в банковской сфере, а с веб-разработкой (непосредственно с Joomla) столкнулся в 2007 году. Теперь это моё хобби и время от времени вторая работа. Какое-то время вёл свой блог, но решил попробовать работать в команде. И вот c 2012 года я здесь :)
timeweb

Заработок в сети

  • Sape - биржа ссылок