От автора: хуки – фундаментальная концепция в WordPress разработке. В этой статье я расскажу вам, как цеплять методы экземпляра класса к экшенам и фильтрам, как интегрировать методы классов со своим пространством имен в хук, какие есть сложности с использованием пространства имен в системе хуков WP, а также мы разберем способы решения данных проблем.
Как прицепить методы объекта
Скажем, ваш босс дал вам задачу написать плагин управления рекламой для крупного новостного сайта, чтобы реклама гладко вставлялась в новостной контент. Тогда вы могли бы сделать следующее.
Вы могли бы создать класс AdManager с парой методов, в которых будет храниться код нескольких рекламных сетей.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class AdManager { /** * AdSense код. */ public function adsense() { ?> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <ins class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-xxxxxxxxxxxxxxxx" data-ad-slot="6762452247"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> <?php } /** * Buysellads код. */ public function buysellads() { // ... } } |
К примеру, в теме сайта есть экшен before_post_content, который запускается до появления контента поста на экране, и вы хотите прицепить метод adsense к нему, чтобы отображать рекламу до загрузки контента. Как бы вы сделали это?
В отличие от примеров из второй части, где мы прикрепляли метод через конструктор класса, вам придется попытаться прицепить метод к экшену не из класса.
1 2 3 |
public function __construct() { add_action( 'before_post_content', array( $this, 'adsense' ) ); } |
Чтобы прицепить метод adsense к экшену before_post_content снаружи класса (возможно, в файле functions.php активной темы) для отображения рекламы Google AdSense еще до загрузки контента поста, вам придется заменить $this на экземпляр класса.
1 |
add_action( 'before_post_content', array( new AdManager(), 'adsense' ) ); |
Скажем, в классе есть метод, возвращающий экземпляр класса по шаблону singleton.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class AdManager { // ... /** * Singleton class instance. * * @return AdManager */ public static function get_instance() { static $instance = null; if ( $instance == null ) { $instance = new self(); } return $instance; } } |
Тогда метод adsense можно прицепить к экшену before_post_content следующим образом.
1 |
add_action( 'before_post_content', array( AdManager::get_instance(), 'adsense' ) ); |
Пространства имен
Система хуков в WP разрабатывалась в то время, когда в WP еще не было пространства имен. Вы можете заметить, что прицепить функции с пространством имен и методы классов к экшенам и фильтрам довольно сложно. Скажем, у класса AdManager пространство имен SitePoint\Plugin.
1 2 3 4 5 6 |
namespace SitePoint\Plugin; class AdManager { // ... } |
Чтобы прицепить метод adsense класса AdManager к экшену before_post_content, необходимо добавить перед именем класса пространство имен:
1 |
add_action( 'before_post_content', array( SitePoint\Plugin\AdManager::get_instance(), 'adsense' ) ); |
Если класс и вызов функции add_action прописаны в пространстве имен SitePoint\Plugin\ одного файла, дописывать пространство имен к имени класса нет необходимости, так как все находится в рамках одного пространства имен. С примерами классов закончили, давайте взглянем на функцию. К примеру, у вас есть следующая функция с пространством имен, которую необходимо прицепить к экшену wp_head.
1 2 3 4 5 |
namespace SitePoint\Plugin; function google_site_verification() { echo '<meta name="google-site-verification" content="ytl89rlFsAzH7dWLs_U2mdlivbrr_jgV4Gq7wClHDUJ8" />'; } |
Прицепить функцию можно, добавив к названию функции пространство имен:
1 |
add_action( 'wp_head', 'SitePoint\Plugin\google_site_verification' ); |
Мой кошмар с пространством имен и системой хуков
В своем плагине Admin Bar & Dashboard Access Control я зарегистрировал хук удаления, который удаляет настройки после удаления плагина.
Что-либо простое наподобие строки ниже сделать легко. PP_Admin_Bar_Control – имя класса, а on_uninstall – метод, вызываемый во время удаления.
1 |
register_uninstall_hook( __FILE__, array( 'PP_Admin_Bar_Control', 'on_uninstall' ) ); |
Чтобы проверить работу хука, я попробовал удалить плагин и посмотреть, удалились ли настройки. К моему удивлению я получил следующую ошибку: The plugin generated 2137 characters of unexpected output during activation.
Посмотрите, как задан класс и функция register_uninstall_hook в пространстве имен ProfilePress\PP_Admin_Bar_Control.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
namespace ProfilePress\PP_Admin_Bar_Control; register_uninstall_hook( __FILE__, array( 'PP_Admin_Bar_Control', 'on_uninstall' ) ); class PP_Admin_Bar_Control { // ... /** Колбэк функция запускается при вызове хука удаления. */ public static function on_uninstall() { if ( ! current_user_can( 'activate_plugins' ) ) { return; } delete_option( 'abdc_options' ); } // ... } |
Видите причину, почему не сработал метод on_uninstall во время удаления плагина? Вам может показаться, что если функция register_uninstall_hook находится в пространстве имен, то и класс будет в нем. Не в этом случае. Необходимо все так же добавлять перед названием метода пространство имен.
1 |
register_uninstall_hook( __FILE__, array( 'ProfilePress\PP_Admin_Bar_Control\PP_Admin_Bar_Control', 'on_uninstall' ) ); |
Я очень долго выяснял, в чем проблема, и решил уберечь вас от той же ошибки.
Заключение
Такие глюки пугают некоторых разработчиков и заставляют отказаться от работы с WP. Не стоит забывать, что WP был разработан в то время, когда сам PHP еще был далек от идеала и не имел всех сегодняшних улучшений и функций. Я всегда пытаюсь понять причину глюка и стараюсь рассказать об этом людям.
Надеюсь, мне удалось снять покров таинственности с системы хуков в WP. Если у вас есть вопросы, или вам есть, что сказать, пишите об этом в комментариях.
Автор: Agbonghama Collins
Источник: //www.sitepoint.com/
Редакция: Команда webformyself.