Advertisement
  1. Code
  2. WordPress

Actions (экшены) и фильтры WordPress: в чём разница?

Scroll to top
Read Time: 9 min

Russian (Pусский) translation by Yuri Yuriev (you can also view the original English article)

Action и фильтры являются основой различных API (наборов функций) WordPress. Без них вы ограничены в своих действиях с темами и (особенно) плагинами.

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

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

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

Определение и отличия

Начнём с определений. Определим функции action и фильтров, чтобы вы увидели разницу между ними.

Функции

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

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

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

Хуки для action.

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

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

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

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

Добавлять фильтры в свой код можно с помощью функции apply_filters (). Как указывает слово «apply», вы применяете фильтры к существующему коду, тогда как action, которое вы создаете с помощью do_action (), пусто, пока вы не подцепите (hook) к нему функцию.  

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

Рассмотрим примеры использования функций, actions и фильтров. Во-первых, мы рассмотрим использование функций непосредственно в вашем коде, без привязки (hook).

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

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

1
if ( ! function_exists( 'compass_colophon' ) ) {
2
function compass_colophon() { ?>
3
    <section class="colophon" role="contentinfo">
4
  	<small class="copyright left">
5
			<?php echo compass_copyright(); ?>
6
			<a href="<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
7
			<?php bloginfo( 'name' ); ?>
8
			</a>
9
		</small><!-- #copyright -->
10
11
		<small class="credits right">
12
				Powered by <a href="https://wordpress.org/">WordPress</a> and designed by <a href="http://compass-design.co.uk">Compass Design</a>.
13
			</a>
14
		</small><!-- #credits -->
15
	</section><!--#colophon-->
16
	<?php }
17
}

Функция подключается в родительской теме, а если создать новую функцию с тем же именем в дочерней теме, она её переопределит. Обратите внимание, что функция содержит в себе ещё одну compass_colophon (), вызывающую её непосредственно в коде.

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

1
compass_colophon();

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

Скоро мы увидим, как эту функцию можно будет подцепить через action или фильтр.

Цепляем функцию к actions

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

Creating Action Hooks (создание хуков для actions)

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

1
do_action( 'compass_in_footer' );

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

Hooking Functions to Actions (подключение функций к actions)

Итак, теперь вместо того, чтобы назначать функцию colophon, я подцеплю её через новый action хук. В файле functions.php я добавлю функцию:

1
add_action( 'compass_in_footer', 'compass_colophon' );

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

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

Допустим, у меня есть ещё одна функция, которую я хочу привязать к моему крюку compass_in_footer, с именем compass_smallprint (), который содержит несколько небольших принтов:

1
if ( ! function_exists( compass_smallprint() ) ) {
2
    function compass_smallprint() {
3
		// contents of function here

4
	}
5
}
6
add_action( 'compass_in_footer', 'compass_smallprint', 20 );

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

Unhooking Functions From Actions (отделение функций от actions)

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

Поэтому, если я хочу, чтобы моя функция compass_smallprint () не запускалась, я отстегну её из action compass_in_footer следующим образом:

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

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

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

Пользуйтесь функцией remove_all_actions():

1
remove_all_actions( 'compass_in_footer' );

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

Подключение функций к фильтрам

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

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

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

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

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

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

1
echo apply_filters( 'compass_colophon', '
2
    <section class="colophon" role="contentinfo">
3
		<small class="copyright left">
4
			<?php echo compass_copyright(); ?>
5
			<a href="<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
6
			<?php bloginfo( 'name' ); ?>
7
			</a>
8
		</small><!-- #copyright -->
9
10
		<small class="credits right">
11
				Powered by <a href="http://wordpress.org/">WordPress</a> and designed by <a href="http://compass-design.co.uk">Compass Design</a>.
12
			</a>
13
		</small><!-- #credits -->
14
	</section><!--#colophon-->'
15
);

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

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

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

1
if ( ! function_exists( 'compass_colophon' ) ) {
2
function compass_colophon() {
3
    echo apply_filters( 'compass_colophon_filter', '
4
		<section class="colophon" role="contentinfo">
5
			<small class="copyright left">
6
				<?php echo compass_copyright(); ?>
7
				<a href="<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
8
				<?php bloginfo( 'name' ); ?>
9
				</a>
10
			</small><!-- #copyright -->
11
	
12
			<small class="credits right">
13
					Powered by <a href="http://wordpress.org/">WordPress</a> and designed by <a href="http://compass-design.co.uk">Compass Design</a>.
14
				</a>
15
			</small><!-- #credits -->
16
		</section><!--#colophon-->'
17
	);
18
}
19
add_action( 'compass_in_footer', 'compass_colophon' );

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

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

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

Поэтому я мог бы создать два фильтра: один для раздела авторских прав и ещё один для кредитов:

1
if ( ! function_exists( 'compass_colophon' ) ) {
2
function compass_colophon() {
3
    
4
	echo '<section class="colophon" role="contentinfo">';
5
		
6
		echo apply_filters( 'compass_copyright_filter', '
7
			<small class="copyright left">
8
				<?php echo compass_copyright(); ?>
9
				<a href="<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
10
				<?php bloginfo( 'name' ); ?>
11
				</a>
12
			</small><!-- #copyright -->'
13
		);
14
		
15
		echo apply_filters( 'compass_copyright_filter', '
16
			<small class="credits right">
17
					Powered by <a href="http://wordpress.org/">WordPress</a> and designed by <a href="http://compass-design.co.uk">Compass Design</a>.
18
				</a>
19
			</small><!-- #credits -->'
20
		);
21
	echo '</section><!--#colophon-->';
22
}
23
add_action( 'compass_in_footer', 'compass_colophon' );

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

Подключение функций к фильтрам

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

Поэтому, чтобы изменить кредиты, я напишу эту функцию:

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

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

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

Отключение функций от фильтров

Как и в случае с хуками action, вы можете отцепить функции от крючков фильтров. Это делается функцией remove_filter (), которая имеет три параметра: имя крюка фильтра, имя функции и приоритет, что является обязательным, если приоритет был задан, когда функция была подключена к фильтру.

Для отключения функции new_credits() делаю так:

1
remove_filter( 'compass_credits_filter', 'new_credits' );

В результате код вернётся к значению, указанному в моей исходной функции apply_filters (). Поэтому, если бы я хотел удалить целиком функцию new_credits () , мне пришлось бы добавить новую функцию в это место. Я отцеплю первую функцию и подключу новую следующим образом:

1
function no_credits() {
2
    return;
3
}
4
remove_filter( 'compass_credits_filter', 'new_credits' );
5
add_filter( 'compass_credits_filter', 'no_credits' );

Итоги

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

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

Помимо подключения своих хуков actions и фильтров, вы можете подключить их к actions и фильтрам, предоставляемым WordPress, например, к action wp_head или фильтру body_class.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.