
Механизм hook'ов (перехватчиков событий) — крайне полезная вещь в WordPress. Они позволяют "подцепить" к некоторым функциям свои собственные, а значит — откорректировать функции WordPress без редактирования базовых файлов. В этой статье мы собрали 10 действительно полезных hook'ов вместе с примерами и объяснениями кода.
Чтобы добиться в блоге WordPress определенного эффекта, нужно изменить способ его работы. В таких случаях зачастую вносятся модификации в файлы, которые разработчики WordPress именуют базовыми — необходимыми для корректной работы WordPress.
Редактирование базовых файлов всегда чревато неприятностями, включая появление брешей в безопасности. Кроме того, после обновления WordPress все изменения будут утеряны.
И все же некоторые функции разработчикам WordPress приходится переписывать, поэтому и появились программные надстройки Plugin API.
Hook'и — один из основных "строительных материалов" для программных модулей WordPress. Практически все модули переписывают базовые функции WordPress с помощью hook`ов.
Все hook`и прописываются в файле "functions.php" (если только речь не идет о создании программного модуля). Данный файл можно найти в папке "wp-content/themes/yourtheme".
Как мы уже говорили, hook`и-перехватчики переопределяют одни функции на другие. Так, например, создав собственную функцию, можно подключить ее к одной из базовых функций WordPress.
add_action ( 'publish_post', 'myCustomFunction' );
В нашем случае мы переопределяем собственную функцию на программную функцию публикации записей "publish-post". Каждый раз при выполнении "publish-post" WordPress будет выполнять и связанную с ней функцию.
Само собой, любые hook`и можно удалить посредством функции "remove_action()".
remove_action ( 'publish_post', 'myCustomFunction' );

Проблема. Возможно, вы заметили, что по умолчанию WordPress заменяет прямые кавычки “парными” и выполняет некоторые другие незначительные действия по форматированию при отображении записи.
Для публикующих нормальное наполнение такая опция удобна, но любого, кто в собственном блоге обсуждает код, это серьезно раздражает: при вставке в текстовый редактор парные кавычки возвращают синтаксическую ошибку.
Решение. Достаточно вставить в файл "functions.php" представленный ниже код:
function my_formatter($content) {
$new_content = '';
$pattern_full = '{(\[raw\].*?\[/raw\])}is';
$pattern_contents = '{\[raw\](.*?)\[/raw\]}is';
$pieces = preg_split($pattern_full, $content, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach ($pieces as $piece) {
if (preg_match($pattern_contents, $piece, $matches)) {
$new_content .= $matches[1];
} else {
$new_content .= wptexturize(wpautop($piece));
}
}
return $new_content;
}
remove_filter('the_content', 'wpautop');
remove_filter('the_content', 'wptexturize');
add_filter('the_content', 'my_formatter', 99);
После этого можно использовать в записях сокращение "[raw]".
[raw]Этот текст не будет автоматически отформатирован.[/raw]
Анализ кода. Первым шагом мы создаем функцию, с помощью обычного выражения ищущую в наполнении записей сокращение "[raw]".
После привязываем функцию "my_formatter()" к программной функции "the_content()". Соответственно, каждый раз при обращении к функции "the_content()" автоматически будет вызываться и "my_formatter()".
Для удаления автоматического форматирования воспользуемся функцией "remove_filter()", позволяющей избавиться от hook'а для конкретной функции.

Проблема. Кросс-браузерная совместимость — едва ли не самая распространенная проблема веб-разработчиков. Возможность распознавать браузеры посетителей веб-сайта снимет массу вопросов — если после распознавания создать собственный класс, заключенный в тэг "body". Хотя об этом знают немногие, в WordPress уже реализована возможность распознавания браузеров плюс предусмотрено несколько глобальных переменных.
Решение. Ничего сложного: вставьте представленный ниже код в файл "functions.php". Теперь осталось его просто сохранить!
<?php
add_filter('body_class','browser_body_class');
function browser_body_class($classes) {
global $is_lynx, $is_gecko, $is_IE, $is_opera, $is_NS4, $is_safari, $is_chrome, $is_iphone;
if($is_lynx) $classes[] = 'lynx';
elseif($is_gecko) $classes[] = 'gecko';
elseif($is_opera) $classes[] = 'opera';
elseif($is_NS4) $classes[] = 'ns4';
elseif($is_safari) $classes[] = 'safari';
elseif($is_chrome) $classes[] = 'chrome';
elseif($is_IE) $classes[] = 'ie';
else $classes[] = 'unknown';
if($is_iphone) $classes[] = 'iphone';
return $classes;
}
?>
После сохранения файла функция будет автоматически добавлять класс таблиц стилей к тэгу "body", как в приведенном ниже примере:
<body class="home blog logged-in safari">
Анализ кода. Глобальные переменные WordPress возвращают "true" при использовании посетителем определенного браузера. Если это Google Chrome, значение "true" вернет переменная "$is_chrome". Поэтому мы создаем функцию "browser_body_class()", возвращающую название браузера пользователя. После этого достаточно переопределить ее на программную функцию "body_class()".

Проблема. Многие блоггеры почти во всех записях используют один и тот же стиль. Записи в моем собственном блоге WpRecipes.com всегда выводятся одинаково: часть текста, часть кода, потом еще текст.
Возможно, стоит сэкономить время, сделав так, что текст по умолчанию будет отображать tinyMCE (визуальный редактор WordPress).
Решение. И снова на помощь приходят hook'и. Откройте файл "functions.php", вставьте код — и предоставьте все остальное им!
<?php
add_filter('default_content', 'my_editor_content');
function my_editor_content( $content ) {
$content = "If you enjoyed this post, make sure to subscribe to my rss feed.";
return $content;
}
?>
Анализ кода. Несмотря на широкие возможности кода, сам метод достаточно просто. Просто создайте функцию, которая возвращает нужный текст (в нашем примере простой текст с предложением о подписке на RSS-ленту блога). Теперь достаточно "подцепить" ее к программной функции "default_content()".

Проблема. Для вставки после записи текста, изображений или рекламы в блогах чаще всего используется шаблон "single.php". Само собой, для этого можно открыть "single.php" и после функции "the_content()" внести нужный текст. Но что если текст не отображается в RSS-ленте? Решить проблему помогут hook'и и описанный ниже прием.
Решение. И снова просто вставьте код в относящийся к нужной теме файл "functions.php". Вот и все.
function insertFootNote($content) {
if(!is_feed() && !is_home()) {
$content.= "<div class='subscribe'>";
$content.= "<h4>Enjoyed this article?</h4>";
$content.= "<p>Subscribe to our <a href='http://feeds2.feedburner.com/WpRecipes'>RSS feed</a> and never miss a recipe!</p>";
$content.= "</div>";
}
return $content;
}
add_filter ('the_content', 'insertFootNote');
Анализ кода. Задача функции "insertFootNote()" предельно ясна: она сцепляет определенный текст с переменной "$content", включающей содержимое записи.
Затем наша функция "insertFootNote()" переопределяется на функцию "the_content()", автоматически вызываясь каждый раз при обращении к "the_content". Принцип работы с данной функцией аналогичен набору текста в конце каждой записи.
Обратите внимание на условие "(!is_feed)" в строке 2, препятствующее вставке текста в RSS-ленту. Чтобы снять это ограничение, замените строку 2 на следующий код:
if (!is_home()) {

Проблема. При выходе новой версии WordPress консоль автоматически дает об этом знать, выводя сообщение в верхнюю часть интерфейса администратора. Вещь это, конечно, нужная, ведь для блога обновления — это новые функции и доработки по безопасности. Но если блог делается под заказ, сообщения об обновлениях уместны далеко не всегда.
Решение. В файл "functions.php" достаточно добавить четыре строки кода.
if (!current_user_can('edit_users')) {
add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ), 2 );
add_filter( 'pre_option_update_core', create_function( '$a', "return null;" ) );
}
После сохранения файла "functions.php" сообщения на консоли вы больше не увидите.
Анализ кода. Первым делом нужно убедиться, что у текущего пользователя есть права администратора, достаточные для обновления WordPress. После этого создаем два hook'а, переписывающие автоматическую проверку обновлений с выводом сообщений.

Проблема. При наборе записи через консоль WordPress периодически сохраняет ее наполнение. Это полезная функция, но иногда возникает потребность ее отключить.
Решение. Для отключения автосохранения в WordPress откройте файл "functions.php" и вставьте следующую функцию:
function disableAutoSave(){
wp_deregister_script('autosave');
}
add_action( 'wp_print_scripts', 'disableAutoSave' );
Анализ кода. И вновь ничего сложного. Мы просто создаем действие (в строке 4) и переопределяем созданную в строке 1 функцию "disableAutoSave()" на программную "wp_print_scripts()".
В результате наша функция "disableAutoSave()" вызывается при каждом выполнении программой "wp_print_scripts()". Тем самым мы отключаем автосохранение в WordPress.

Проблема. Дублирование наполнения — SEO-проблема многих сайтов. Она может стать актуальной и для вашего блога, если только не воспользоваться некоторыми хитростями.
Появившийся в версии 2.7 постраничный вывод комментариев (paged comments) стал ценным дополнением к WordPress, поскольку теперь блоггеры получили возможность разбивать массу комментариев на несколько страниц. Единственная проблема при этом, как уже упоминалось выше, — риск дублирования наполнения.
Чтобы избежать дублирования в постраничных комментариях, воспользуемся новым атрибутом rel="canonical".
Решение. Просто вставьте представленный ниже код в файл "function.php".
function canonical_for_comments() {
global $cpage, $post;
if ( $cpage > 1 ) :
echo "\n";
echo "<link rel='canonical' href='";
echo get_permalink( $post->ID );
echo "' />\n";
endif;
}
add_action( 'wp_head', 'canonical_for_comments' );
Анализ кода. Первым шагом создаем функцию, добавляющую к комментариям страниц (за исключением страницы 1) атрибут rel="canonical". После переориентируем ее на программную функцию "wp_head()". Только и всего!

Проблема. Возможность превратить текущую запись или страницу в PHP-переменную определенно полезна. Среди прочего можно, например, заменить часть наполнения с помощью PHP-функции "str_replace()".
Решение. И снова ничего сложного. Просто вставьте код в файл "functions.php".
function callback($buffer) {
//модифицируем буфер и возвращаем обновленный код
return $buffer;
}
function buffer_start() {
ob_start("callback");
}
function buffer_end() {
ob_end_flush();
}
add_action('wp_head', 'buffer_start');
add_action('wp_footer', 'buffer_end');
Анализ кода. Для этого приема нам понадобятся три функции:
- callback(): данная функция возвращает страницу целиком в виде переменной "$buffer". Перед этим можно модифицировать ее с помощью стандартных выражений.
- buffer_start(): данная функция просто запускает буфер, переопределяясь на программную функцию "wp_head()".
- buffer_end(): данная функция очищает буфер, переопределяясь на программную функцию "wp_footer()".
Как только наша функция будет готова, просто свяжем ее с программными функциями WordPress.

Проблема. Как вы, возможно, знаете, в WordPress есть возможность планировать события, например, публикуя записи в предварительно заданные дни и часы. С помощью hook'ов и "wp-cron" легко запланировать свои собственные события. В нашем примере блог WordPress раз в час будет отправлять нам электронное сообщение.
Решение. Вставьте блок с приведенным ниже кодом в относящийся к нужной теме файл "functions.php".
if (!wp_next_scheduled('my_task_hook')) {
wp_schedule_event( time(), 'hourly', 'my_task_hook' );
}
add_action( 'my_task_hook', 'my_task_function' );
function my_task_function() {
wp_mail('you@yoursite.com', 'Automatic email', 'Hello, this is an automatically scheduled email from WordPress.');
}
Анализ кода. Первым делом, мы, конечно же, создали функцию, выполняющую нужное действие. В данном примере это функция "my_task_function()", которая просто отправляет сообщение на указанный адрес электронной почты.
Чтобы запланировать событие, воспользуемся функцией "wp_schedule_event()". Последним аргументом должен быть hook, вот почему мы переопределяем функцию "my_task_function()" на "my_task_hook".

Проблема. Если что-то пошло не так, при отладке удобно видеть список всех связанных функций.
Решение. Как и в предыдущих примерах, достаточно вставить предложенный код в файл "functions.php". По окончании отладки не забудьте удалить его из файла, иначе служебное сообщение будет появляться и дальше.
function list_hooked_functions($tag=false){
global $wp_filter;
if ($tag) {
$hook[$tag]=$wp_filter[$tag];
if (!is_array($hook[$tag])) {
trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
return;
}
}
else {
$hook=$wp_filter;
ksort($hook);
}
echo '<pre>';
foreach($hook as $tag => $priority){
echo "<br />>>>>>\t<strong>$tag</strong><br />";
ksort($priority);
foreach($priority as $priority => $function){
echo $priority;
foreach($function as $name => $properties) echo "\t$name<br />";
}
}
echo '</pre>';
return;
}
Сделав это, просто вызовите функцию "list_hooked_functions()", как показано ниже, для вывода на экран всех функций WordPress с hook'ами.
list_hooked_functions();
Анализ кода. Если в качестве аргумента функции не дается имя hook'а, то hook'и выводятся на экран посредством глобальной переменной "$wp_filter". Альтернативный вариант: отображение в списке конкретного hook'а при передаче его имени в качестве атрибута:
list_hooked_functions('wp_head');
Перевод статьи: 10 Useful WordPress Hook Hacks
Из всей статьи может пригодиться только 4 пункт. Остальное вообще не представляю где и зачем использовать 🙂
на хабре читал 🙂
😀
полезные хуки, у меня как новичка, вопрос-есть хук который бы автоматизировал бы одобрение комментов? Akismet стоит.
Дмитрий, подскажите как реализовать такую идею.
Не секрет, что сайты использующие контент партнерских программ, часто попадают в бан за неуникальность.
Вариант рерайтить описания тех же фильмов, довольно таки накладно, поэтому хочу сделать следующее:
Написать общий текст для всех страничек, размножить генератором, выбрать определеное количество уникальных и добавлять их к описаниям (записям) после функции "the_content()"
Типа
Размноженный текст №1
То есть не ручками после публикации каждой записи, а настроить один раз и на автомате исполнять.
Надеюсь правильно объяснил %)
P.S. Спасибо за блог, много ценной информации.
Ах да, если сочтете, что эта просьба из раздела платных услуг, то я не жадный =)
Исправляю, где
Размноженный текст №1
Читать
[?php if ( is_single(ID) ) { ?]
Размноженный текст №1
[?php }?]
Здравствуйте. У меня такая проблема. Я хочу, чтобы при публикации записи В ПЕРВЫЙ РАЗ отправлялось сообщение на почту. Вроде всё хорошо. Только отправляется сообщение не только после перехода из статуса "Черновик" в статус "Опубликовано", а ещё и при каждом редактировании/сохранении записи. Может вы подскажете, как справиться с этою бедой. Спасибо.
function sendmessage()
{
global $post;
$to .= 'ID, 'author_email', true) .'>';
$subject = "Your company has published";
$message .= "Congratulations! Your company has been added to the list";
$headers .= "From: Hosting Review \r\n";
@mail($to, $subject, $message, $headers);
}
add_action ('publish_post', 'sendmessage' );
Смешной Новостной, не знаю точно. Как-то так:
function sendmessage()
{
global $post;
if ( (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || $post->post_status=='draft' ) return;
...
Недавно обратил внимание на огромный размер дампа базы данных, как отключить авто сохранение, вроде понятно. А как теперь почистить саму базу?
Спасибо, делал рекламу на своём адалтнике, нужно было вставить код после каждой новости в WP.
Помогли вот эти Ваши строчки из статьи:
"Для вставки после записи текста, изображений или рекламы в блогах чаще всего используется шаблон "single.php". Само собой, для этого можно открыть "single.php" и после функции "the_content()" внести нужный текст."
Большое спасибо!
Всё никак не могу найти возможность поменять футер на лету.. Благодарю за п.8!
На хабре не мой перевод, кто то другой перевел, а я и не заметил и мучился сам переводил ;(