Механизм 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!
На хабре не мой перевод, кто то другой перевел, а я и не заметил и мучился сам переводил ;(