Как работают хуки wordpress
Перейти к содержимому

Как работают хуки wordpress

  • автор:

WordPress. Как работают хуки

В процессе загрузки WordPress происходит множество событий. К каждому из этих событий можно привязать функцию, которая выполнит какое-то действие ( action ) или изменит данные ( filter ). Разделение нужно, потому что по смыслу это разные вещи. Действие просто отрабытывает в нужный момент и ничего не возвращает, а фильтр — обрабатывает переданные данные и обязательно должен их вернуть.

Как работают хуки

Это упрощенный вариант реализации хуков, который наглядно показывает, как это работает:

$actions = array(); function add_action($hook, $function)  global $actions; if (!isset($actions[$hook]))  $actions[$hook] = array(); > $actions[$hook][] = $function; > function do_action($hook)  global $actions; if (isset($actions[$hook]))  foreach($actions[$hook] as $function)  call_user_func($function); > > >

Функция add_action() назначает обработчик $function для события $hook . Функция do_action() инициирует событие $hook , после чего вызываются на выполнение все функции-обработчики этого события.

Примеры хуков-действий

// создадим функцию для хука function echo_one()  echo 'one'; > // привяжем функцию к хуку add_action('some_hook', 'echo_one'); // выполним хук do_action('some_hook'); // выведет «one»
// создадим функции для событий function echo_one($data)  echo $data[0]; > function echo_two($data)  echo $data[1]; > // привяжем эти функции к хуку add_action('some_hook', 'echo_one'); add_action('some_hook', 'echo_two'); // выполним хук do_action('some_hook', array('Привет', ' мир!') ); // выведет «Привет мир!»

Функция add_action()

add_action($hook, $function, $priority, $count);

Прикрепляет указанную функцию на указанный хук. Функция $function сработает в момент события $hook , которое в свою очередь запускается с помощью do_action() .

Функция do_action()

do_action($hook, $arg1, $arg2,);

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

Примеры хуков-фильтров

// создадим функцию для хука function some_filter($str)  return 'Привет ' . $str . '!'; > // привяжем функцию к хуку add_filter('some_hook', 'some_filter'); // выполним хук $data = apply_filters('some_hook', 'мир'); // посмотрим, что получилось echo $data; // выведет «Привет мир!»
// создадим функцию для хука function crop_string($string)  return iconv_substr($string, 0, 6) . '…'; > // привяжем функции к хуку add_filter('prepare_string', 'strip_tags'); add_filter('prepare_string', 'crop_string'); // выполним хук $data = apply_filters('prepare_string', '

Привет, мир!

'
); // посмотрим, что получилось echo $data; // выведет «Привет…»

Функция add_filter()

add_filter($hook, $function, $priority, $count);

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

Функция apply_filters()

apply_filters($hook, $value, $arg1, $arg2,);

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

  • WordPress. Порядок загрузки страницы
  • WordPress. Создание одностраничного сайта
  • WordPress. Обработка POST-запросов. Часть 1
  • WordPress. Форма комментирования
  • WordPress. Теги шаблона
  • WordPress. Установка и использование WP-CLI
  • WordPress. Обработка POST-запросов. Часть 2

Каталог оборудования

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Производители

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Функциональные группы

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Категории блога
Облако тегов

  • 1С:Предприятие (31)
  • API (29)
  • Bash (43)
  • CLI (122)
  • CMS (139)
  • CSS (50)
  • Frontend (75)
  • HTML (66)
  • JavaScript (150)
  • Laravel (72)
  • Linux (169)
  • MySQL (76)
  • PHP (125)
  • React.js (66)
  • SSH (27)
  • Ubuntu (69)
  • Web-разработка (509)
  • WordPress (73)
  • Yii2 (69)
  • БазаДанных (95)
  • Битрикс (66)
  • Блог (29)
  • Верстка (43)
  • ИнтернетМагаз… (84)
  • КаталогТоваров (87)
  • Класс (30)
  • Клиент (28)
  • Ключ (28)
  • Команда (87)
  • Компонент (60)
  • Конфигурация (64)
  • Корзина (32)
  • ЛокальнаяСеть (32)
  • Модуль (34)
  • Навигация (31)
  • Настройка (141)
  • ПанельУправле… (29)
  • Плагин (33)
  • Пользователь (26)
  • Практика (101)
  • Сервер (75)
  • Событие (27)
  • Теория (106)
  • Установка (66)
  • Файл (51)
  • Форма (58)
  • Фреймворк (192)
  • Функция (36)
  • ШаблонСайта (68)

Хуки: фильтры и действия. Подробное руководство

Хук (hook) — в переводе означает крючок.

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

Наши хуки будут делиться на два вида: фильтры и действия.

  • Фильтры позволят вам изменить значения каких-либо переменных перед их возвратом функциями.
  • Действия позволят вам выполнить какой угодно код там, где висит «крючок».

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

Пошаговый разбор работы фильтра

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

Делается это в принципе при помощи двух функций — apply_filters() и add_filter().

  1. Всё начинается с того, что где-то в коде движка WordPress или плагина находится переменная, на которую в последствии нужно будет воздействовать фильтром. На эту переменную вешается функция apply_filters(), и результат действия функции обычно присваивается самой же переменной. Кроме того, тут же задаётся и название фильтра. Например это может выглядит так:
$x = apply_filters( 'misha_filter', $x );
  1. После этого мы уже можем воздействовать на эту переменную извне при помощи add_filter(). Для этого например в файле functions.php или в нашем собственном плагине, который мы разрабатываем на протяжении этого курса, мы создаём функцию с произвольным названием, аргумент функции — переменная $x , внутри функции выполняем с ней все необходимые действия и в конце концов возвращаем результативную переменную. Затем, рядом с функцией вызываем add_filter(), в которой в качестве параметров указываем название фильтра и название нашей произвольной функции. Меньше слов, больше дела — вот как это может выглядеть:
add_filter( 'misha_filter', 'misha_function' ); function misha_function( $x ) { $x = '' . $x . ''; // если переменная текстовая, мы просто сделали текст жирным шрифтом return $x; // возвращаем }

Или вот так начиная с версии PHP 5.3

add_filter( 'misha_filter', function( $x ) { $x = '' . $x . ''; // если переменная текстовая, мы просто сделали текст жирным шрифтом return $x; // возвращаем } );

Но у анонимной функции есть минус – такой хук невозможно будет отключить.

  1. Стоп! Прежде, чем читать пост дальше, рекомендую опробовать всё это у себя. Вам не обязательно писать для этого плагин — просто в теме, например в header.php выведите переменную $x и перед выводом примените к ней фильтр, а в файле functions.php этот фильтр и наложите.

Пример с фильтром the_content

Скажите, то содержимое поста, которое находится у вас в редакторе в админке и то, которое выводится на сайте одно и то же или отличается?

Вероятно, это одна из тех вещей, которая фильтруется больше всего – при помощи фильтра the_content на содержимое поста накладываются функции wpautop(), wptexturize(), применяются шорткоды. Кроме того, пользователь тоже мог нагуглить какие-нибудь хуки и с их помощью, скажем, выводить кнопки социальных сетей под постом.

Наглядная аналогия фильтра the_content в WordPress

Чтобы посмотреть наглядно, попробуйте вставить этот код в удобное место в теме, в footer.php или в произвольный шаблон страницы:

$my_post = get_post( 5 ); // вместо 5 укажите ID интересующей вас записи echo $my_post->post_content; // выводим содержимое поста как оно есть в базе данных $filtered = apply_filters( 'the_content', $my_post->post_content ); // применяем фильтры echo $filtered; // выводим, смотрим, что получилось

Пошаговый разбор работы хука действия

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

Делается всё это так же, как и в случае с фильтрами, двумя функциями — do_action() и add_action()

  1. Всё начинается с того, что где-то в коде есть место, в котором потенциально нужно будет выполнить дополнительный код. Это место мы обозначим функцией do_action(), в качестве параметра которой укажем название «крючка». Это будет выглядеть очень просто:
do_action( 'misha_hook' );
  1. Теперь на этот «крючок» мы уже можем повесить функцию, которая будет находиться например в functions.php вашем темы или в отдельном плагине. То есть открываем functions.php , создаём там произвольную функцию, затем рядом с ней (не в ней!) выполняем функцию add_action(), в которой указываем название хука и название произвольной функции.
add_action( 'misha_hook', 'misha_function2' ); function misha_function2(){ echo 'Привет, мир!'; }

Ну разве не простой механизм?

Пример с использованием хука wp_head в WordPress

Просто wp_head это первое, что пришло мне сейчас в голову. Итак, прежде всего откройте страницу вашего сайта, откройте её и в виде HTML-кода в браузере. А теперь зайдите в файл header.php и быстрым нажатием клавиши удалите оттуда функцию wp_head() (она и запускает хук). После этого посмотрите, как сильно изменится ваша страница — исчезнут стили, скрипты, возможно какой-то произвольный код, который вы вручную добавляли через этот хук.

Параметры и приоритеты

Приоритеты

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

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

add_action( 'misha_priority', function(){ echo 'A'; } ); add_action( 'misha_priority', function(){ echo 'Б'; } ); add_action( 'misha_priority', function(){ echo 'В'; } ); // сам хук do_action( 'misha_priority' ); // будет выведено АБВ

А теперь внимание — функции add_action() и add_filter() третьим параметров поддерживают указание приоритета, с учетом этого видоизменим наш код.

add_action( 'misha_priority', function(){ echo 'A'; }, 9999 ); add_action( 'misha_priority', function(){ echo 'Б'; }, 5 ); add_action( 'misha_priority', function(){ echo 'В'; }, 10 ); // 10 - значение по умолчанию, поэтому его можно и не указывать // сам хук do_action( 'misha_priority' ); // будет выведено БВА

Как видите, чем выше значение приоритета, тем позднее функция будет подключена к хуку и выполнена.

Передача дополнительных аргументов в функцию

Чего ещё не хватает для полного счастья — передачи в подвешенные на хук функции дополнительных параметров. И эта возможность тоже предусмотрена.

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

do_action( 'misha_action', $param1, $param2, $param3 );

После этого, четвёртым параметром функции add_action() или add_filter() соответственно вы можете решить, сколько из них можно передать непосредственно в функцию.

add_action( 'misha_action', 'misha_function_1', 10, 3 ); // 3 - количество параметров, можно указать и 2, тогда функция misha_function() примет только два параметра, единицу можно не указывать, так как это значение по умолчанию function misha_function_1( $param1, $param2, $param3 ) { . }

Отключение хуков и действий

Всего для этих целей в WordPress существует 4 функции:

  • remove_filter() — для отключения конкретной функции с фильтра.
  • remove_action() — для удаления конкретной функции с хука действия.
  • remove_all_filters() — для полной очистки хука фильтра.
  • remove_all_actions() — для полной очистки хука действия.

Пример для WooCommerce, удаляющий опции сортировки со страницы «Магазин» и категорий товаров:

remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );

Купить курс

  • 11 видеоуроков
  • Можно скачать готовый код после каждого урока
  • Можно начать проходить курс сразу же после оплаты
  • Единоразовый платёж
  • Доступ навсегда
  • Уроки актуальны в 2023-м году

10 полезных хук-хаков для WordPress

image

О том, что такое хуки в WordPress и как их там использовать. Статья молодого WordPress-специалиста, владельца сайта www.wprecipes.com, из Бельгии.

ВВЕДЕНИЕ

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

ЧТО ТАКОЕ ХУК?

Для достижения определенного эффекта нам нужно слегка изменить принцип работы WordPress. Некоторые модификации необходимо внести в файлы, которые были названы разработчиками файлами ядра – они нужны для того, чтобы WordPress работал должным образом.
Но изменение файлов ядра – плохая идея: это может создать брешь в системе безопасности блога. Также, все модификации исчезнут, как только Вы обновите движок до новой версии.
Однако, расширение функциональности все же необходимо. Для этого разработчиками был придуман Plugin API.
Хуки являются одним из главных блоков для построения плагинов. Почти каждый подключаемый плагин использует хуки для расширения функциональности WordPress.

КАК ИСПОЛЬЗОВАТЬ ХУКИ В ВАШЕМ БЛОГЕ

Пока Вы не написали свой плагин, Вы должны записать хуки в файл functions.php. Этот файл находится в директории wp-content/themes/yourtheme (где /yourtheme – директория, в которой находится текущая тема).
Вот пример, который показывает, как подключить Вашу пользовательскую функцию к функции ядра движка:

  1. add_action ( ‘publish_post’ , ‘myCustomFunction’ ) ;

В этом примере мы подключили пользовательскую функцию myCustomFunction() к функции ядра publish_post(). Функция myCustomFunction() будет выполняться при каждом выполнении функции publish_post().
Конечно, мы можем также удалить хук, используя функцию remove_action():

  1. remove_action ( ‘publish_post’ , ‘myCustomFunction’ ) ;

1. ОТКЛЮЧАЕМ АВТОМАТИЧСКОЕ ФОРМАТИРОВАНИЕ В WORDPRESS

Проблема.

Вы, наверное, уже замечали, что типограф WordPress по умолчанию превращает «прямые» кавычки в «кривые» и делает другие мелкие изменения в форматировании поста.
Это хорошо, если блоггер размещает обычный контент (подразумеваются обычный текст и картинки). Но некоторые постят исходный код, чтобы потом его обсуждать, и они будут очень недовольны, когда из-за этих «кривых» кавычек интерпретатор иди компилятор выдадут им сообщения о синтаксических ошибках.

Решение.

Просто вставьте в файл functions.php нижеследующий код:

  1. function my_formatter ( $content )
  2. $new_content = » ;
  3. $pattern_full = ‘<(\[raw\].*?\[/raw\])>is’ ;
  4. $pattern_contents = ‘is’ ;
  5. $pieces = preg_split ( $pattern_full , $content , — 1 , PREG_SPLIT_DELIM_CAPTURE ) ;
  6. foreach ( $pieces as $piece )
  7. if ( preg_match ( $pattern_contents , $piece , $matches ) )
  8. $new_content .= $matches [ 1 ] ;
  9. > else
  10. $new_content .= wptexturize ( wpautop ( $piece ) ) ;
  11. >
  12. >
  13. return $new_content ;
  14. >
  15. remove_filter ( ‘the_content’ , ‘wpautop’ ) ;
  16. remove_filter ( ‘the_content’ , ‘wptexturize’ ) ;
  17. add_filter ( ‘the_content’ , ‘my_formatter’ , 99 ) ;

После того, как Вы это сделали, можете использовать тэг [raw] для того, чтобы текст поста был не отформатирован автоматически:

[raw]This text will not be automatically formatted.[/raw]

Объяснение кода.

Первым делом, мы создаем функцию, которая, основываясь на регулярных выражениях, находит тэг [raw] в содержании Вашего поста.
Далее, мы привязываем нашу функцию my_formatter() к функции the_content(), что означает выполнение нашей функции всякий раз, когда вызывается функция the_content().
Для того, чтобы отключить автоформатирование, мы использовали функцию remove_filter().

2. ОПРЕДЕЛЯЕМ БРАУЗЕР ПОСЕТИТЕЛЯ ПРИ ПОМОЩИ ХУКОВ

Проблема.

Кросс-браузерная совместимость – это наиболее распространенная проблема в web-разработке. Вы сэкономите много нервов и времени, если сможете определить браузер пользователя, зашедшего на Ваш блог, а затем создав CSS-класс для тэга body под каждый из браузеров.

Решение.

Ничего сложного: просто вставьте нижеследующий код в файл functions.php, сохраните его – все готово!

  1. add_filter ( ‘body_class’ , ‘browser_body_class’ ) ;
  2. function browser_body_class ( $classes )
  3. global $is_lynx , $is_gecko , $is_IE , $is_opera , $is_NS4 , $is_safari , $is_chrome , $is_iphone ;
  4. if ( $is_lynx ) $classes [ ] = ‘lynx’ ;
  5. elseif ( $is_gecko ) $classes [ ] = ‘gecko’ ;
  6. elseif ( $is_opera ) $classes [ ] = ‘opera’ ;
  7. elseif ( $is_NS4 ) $classes [ ] = ‘ns4’ ;
  8. elseif ( $is_safari ) $classes [ ] = ‘safari’ ;
  9. elseif ( $is_chrome ) $classes [ ] = ‘chrome’ ;
  10. elseif ( $is_IE ) $classes [ ] = ‘ie’ ;
  11. else $classes [ ] = ‘unknown’ ;
  12. if ( $is_iphone ) $classes [ ] = ‘iphone’ ;
  13. return $classes ;
  14. >

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

Объяснение кода.

WordPress имеет глобальные переменные, которые возвращают true, если пользователь использует соответствующий браузер. Если пользователь использует браузер Google Chrome, то переменная $is_chrome примет значение true. Вот для чего мы и создаем функцию browser_body_class(). После этого мы присоединяем ее к WordPress функции body_class().

3. ОПРЕДЕЛЕНИЕ ТЕКСТА ПО УМОЛЧАНИЮ В РЕДАКТОРЕ TinyMCE

Проблема.

Многие блоггеры почти всегда используют для своего блога один и тот же формат. Сообщения в моем блоге WpRecipes.com всегда отображаются одинаково: текст, код, еще немного текста.
Можно сэкономить немало времени, если научить TinyMCE отображать какой-нибудь текст по умолчанию.

Решение.

Как всегда, решением является хук. Копируем код в файл functions.php и смотрим, как он работает.

  1. add_filter ( ‘default_content’ , ‘my_editor_content’ ) ;
  2. function my_editor_content ( $content )
  3. $content = «If you enjoyed this post, make sure to subscribe to my rss feed.» ;
  4. return $content ;
  5. >
Объяснение кода.

Этот код хоть и простой, но очень мощный. Просто создаем функцию, которая возвращает требуемый текст (в этом примере мы определяем текст, который спрашивает у посетителей о подписке на RSS-ленту), и присоединяем ее к WordPress-функции default_content(). Вот так.

4. ВСТАВЛЯЕМ КОНТЕНТ АВТОМАТИЧЕСКИ ПОСЛЕ КАЖДОГО ПОСТА

Проблема.

В большинстве блогов для вывода контента после каждого поста файл single.php, но вот беда: этот контент не будет отображаться в RSS-ленте. Хуки помогут исправить эту проблему.

Решение.

Все то же самое – просто копируем следующий код в файл fucntions.php.

  1. function insertFootNote ( $content )
  2. if ( ! is_feed ( ) && ! is_home ( ) )
  3. $content .= «
  4. $content .= «
    Enjoyed this article?

    » ;

  5. $content .= «

    Subscribe to our RSS feed and never miss a recipe!

    » ;

  6. $content .= «

» ;

  • >
  • return $content ;
  • >
  • add_filter ( ‘the_content’ , ‘insertFootNote’ ) ;
  • Объяснение кода.

    Суть функции insertFootNote() проста: он лишь конкатенирует желаемый текст к переменной $content, в которой хранится содержание поста.
    Затем, мы присоединяем нашу функцию insertFootNote() к функции the_content().
    Видите в строке 2 вот такой код:

    1. if ( ! is_feed ( ) && ! is_home ( ) )

    Если Вам нужно, чтобы текст попадал в RSS-ленту, то замените предыдущий код на этот:

    5. ОТКЛЮЧАЕМ СООБЩЕНИЕ С ПРОСЬБОЙ ОБНОВИТЬСЯ В ПАНЕЛИ УПРАВЛЕНИЯ WORDPRESS

    Проблема.

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

    Решение.

    Просто вставьте следующий код в файл fucntions.php.

    1. if ( ! current_user_can ( ‘edit_users’ ) )
    2. add_action ( ‘init’ , create_function ( ‘$a’ , «remove_action( ‘init’, ‘wp_version_check’ );» ) , 2 ) ;
    3. add_filter ( ‘pre_option_update_core’ , create_function ( ‘$a’ , «return null;» ) ) ;
    4. >

    После того, как Вы сохраните файл functions.php, сообщения Вы больше не увидите.

    Объяснение кода.

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

    6. ОТКЛЮЧАЕМ АВТОСОХРАНЕНИЕ ПОСТОВ

    Проблема.

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

    Решение.

    Для того, чтобы отключить автосохранение поста, просто откройте файл functions.php и вставьте в него следующий код.

    1. function disableAutoSave ( )
    2. wp_deregister_script ( ‘autosave’ ) ;
    3. >
    4. add_action ( ‘wp_print_scripts’ , ‘disableAutoSave’ ) ;
    Объяснение кода.

    И вновь, ничего сложного: мы просто создаем функцию, которая отключается автосохранение и привязываем ее к WordPress-функции wp_print_scripts().

    7. ИЗБАВЛЯЕМСЯ ОТ ПОВТОРЯЮЩЕГОСЯ КОНТЕНТА НА СТРАНИЦАХ С КОММЕНТАРИЯМИ

    Проблема.

    Повторяющийся контент эта довольно распространенная SEO-проблема.
    Введенная в WordPress версии 2.7 система разбиения комментариев на страницы эту проблему не решает.
    Для предупреждения повторяющегося контента в комментариях будем использовать атрибут rel=«canonical».

    Решение.

    Копируем следующий код и вставляем его в файл functions.php.

    1. function canonical_for_comments ( )
    2. global $cpage , $post ;
    3. if ( $cpage > 1 ) :
    4. echo » \n » ;
    5. echo »
    6. echo get_permalink ( $post -> ID ) ;
    7. echo «‘ /> \n » ;
    8. endif ;
    9. >
    10. add_action ( ‘wp_head’ , ‘canonical_for_comments’ ) ;
    Объяснение кода.

    Сначала, мы создаем функцию, которая добавляет к каждой странице с комментариями, кроме первой, тэг link с атрибутом rel=«canonical». Затем, присоединяем эту функцию к WordPress-функци wp_head().

    8. ПОЛУЧЕНИЕ ПОСТА ИЛИ СТРАНИЦЫ В КАЧЕСТВЕ PHP-ПЕРЕМЕННОЙ

    Проблема.

    Возможность получить текущий пост или целую страницу в качестве PHP переменной – действительно крутая вещь. Скажем, Вы можете заменять некоторые части контента при помощи функции str_replace() или делать с ним еще что-нибудь.

    Решение.

    И снова ничего сложного. Делаем все то же самое: вставляем следующий код в файл functions.php.

    1. function callback ( $buffer )
    2. // modify buffer here, and then return the updated code
    3. return $buffer ;
    4. >
    5. function buffer_start ( )
    6. ob_start ( «callback» ) ;
    7. >
    8. function buffer_end ( )
    9. ob_end_flush ( ) ;
    10. >
    11. add_action ( ‘wp_head’ , ‘buffer_start’ ) ;
    12. add_action ( ‘wp_footer’ , ‘buffer_end’ ) ;
    Объяснение кода.
    • callback(): эта функция возвращает страницу целиком как переменную $buffer. Вы можете модифицировать ее как угодно, например, при помощи регулярных выражений;
    • buffer_start(): эта функция начинает буферизацию. Ее мы присоединяем к функции wp_head();
    • buffer_end(): эта функция очищает буфер. Ее мы присоединяем к функции wp_footer().

    9. ИСПОЛЬЗУЕМ ХУКИ И CRON ДЛЯ СОБЫТИЙ ПО РАСПИСАНИЮ

    Проблема.

    Вы, наверное, уже знаете, что WordPress может использовать события по расписанию. К примеру, можно публиковать посты в конкретное, установленное заранее, время. Используя хуки и wp-cron, мы можем запросто задать расписание для нашего собственного события. В следующем примере мы заставим блог отправлять нам сообщения на e-mail один раз каждый час.

    Решение.

    Вставляем следующий код в файл functions.php.

    1. if ( ! wp_next_scheduled ( ‘my_task_hook’ ) )
    2. wp_schedule_event ( time ( ) , ‘hourly’ , ‘my_task_hook’ ) ;
    3. >
    4. add_action ( ‘my_task_hook’ , ‘my_task_function’ ) ;
    5. function my_task_function ( )
    6. wp_mail ( ‘you@yoursite.com’ , ‘Automatic email’ , ‘Hello, this is an automatically scheduled email from WordPress.’ ) ;
    7. >
    Объяснение кода.

    Первое, что мы сделаем, конечно, — это создадим функцию, которая будет выполнять требуемое действие. В этом примере эта функция называется my_task_function() и она просто отправляет письмо на указанный e-mail адрес.
    Для того, чтобы запланировать выполнение этой функции, мы будем использовать функцию wp_schedule_event(). Последним аргументом, передаваемым ей, будет наш хук, поэтому мы «цепляем» нашу функцию my_task_function() к my_task_hook.

    10. СПИСОК ВСЕХ «ХУКНУТЫХ» ФУНКЦИЙ

    Проблема.

    Когда что-то идет не так, здорово может пригодиться список всех «хукнутых» функций.

    Решение.

    Как и все предыдущие фрагменты кода следующий также необходимо вставить в файл functions.php. Только не забудьте удалить его после использования. Если Вы этого не сделаете, то сообщения будут появляться и после отладки.

    1. function list_hooked_functions ( $tag = false )
    2. global $wp_filter ;
    3. if ( $tag )
    4. $hook [ $tag ] = $wp_filter [ $tag ] ;
    5. if ( ! is_array ( $hook [ $tag ] ) )
    6. trigger_error ( «Nothing found for ‘ $tag ‘ hook» , E_USER_WARNING ) ;
    7. return ;
    8. >
    9. >
    10. else
    11. $hook = $wp_filter ;
    12. ksort ( $hook ) ;
    13. >
    14. echo ‘
      ' ;
    15. foreach ( $hook as $tag => $priority )
    16. echo "
      >>>>> \t $tag
      " ;
    17. ksort ( $priority ) ;
    18. foreach ( $priority as $priority => $function )
    19. echo $priority ;
    20. foreach ( $function as $name => $properties ) echo " \t $name
      " ;
    21. >
    22. >
    23. echo '

      ‘ ;

    24. return ;
    25. >

    После того, как Вы вставите этот код в файл functions.php, вызовите функцию list_hooked_functions(). Она и покажет Вам список всех «хукнутых» функций.

    Объяснение кода.

    Данный код выясняет, передается ли имя хука в качестве аргумента функции. Если передается, то на экран выводится имя хука. Также можно посмотреть хуки только для определенной функции:

    1. list_hooked_functions ( ‘wp_head’ ) ;

    Что такое WordPress хуки и как их использовать?

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

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

    Я учавствовал в несколько десятках технических интервью и был сильно удивлен, что некоторые разработчики WordPress понимают эту, на мой взгляд важнейшую, тему поверхностно, интуитивно или вообще не знают, как работают хуки. Лично я считаю, что данная тема является обязательной и самой важной для разработчиков WordPress, поэтому я решил описать ее еще раз. В любом случае, давайте начнем.

    Хуки — это Действия (Actions) и Фильтры (Filters)

    Действия (Actions) разрешают вам добавить данные или изменить поведение WordPress. Действия будут запускаться в определенный момент внутри WordPress ядра, плагинов или тем. Колбэки (Callback functions) для действий могут выполнять разные задачи, такие как пользовательский вывод или добавление чего-нибудь в базу данных. Колбэки для действий ничего не возращают назад при добавлении на хук.

    Документация для WordPress разработчиков

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

    Документация для WordPress разработчиков

    В двух словах, действия запускают какой-нибудь код, а фильтры — изменяют переменные. Давайте рассмотрим пару примеров:

    add_action( 'save_post', 'notify_administrator', 10, 3 ); function notify_administrator( $post_id, WP_Post $post, $update ) < // Really important code here . wp_mail( $admin_email, $subject, $message ); >add_filter( 'post_class', 'modify_post_classes', 10, 3 ); function modify_post_classes( $classes, $class, $post_id ) < if ( in_array( get_post_type( $post_id ), [ 'review', 'service' ] ) ) < $classes[] = 'dark-theme'; >return $classes; >

    Обратите внимание, что колбэк для фильтра ( modify_post_classes ) обязательно должен вернуть данные, немного измененные или похожие на те, которые он принимает первым аргументом ( $classes ).

    Как технически работают хуки?

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

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

    Вот, упрощенный пример:

    // Запуск кода. // Загружаем 1-й плагин add_action( 'before_magic', 'say_hi' ); // Записываем в хранилище // Загружаем 2-й плагин add_action( 'before_magic', 'introduce_yourself' ); // Записываем в хранилище // Загрузили все плагины // Загружаем активную тему add_action( 'after_magic', 'applause' ); // Записываем в хранилище // Загрузили тему function magic() < do_action( 'before_magic' ); // Запускаем все колбэк-фукнкции из хранилища, которые относятся к этому действию. Но после запуска самой фукнции (не сейчас, чуть позже) $this->take_hat(); $this->stick_your_hand_in_your_hat(); $this->get_hare(); do_action( 'after_magic' ); // Запускаем все колбэк-фукнкции из хранилища, которые относятся к этому действию. Но после запуска самой фукнции (не сейчас, чуть позже) > // Несколько миллисекунд спустя. // Запускаем какую-то страницу в которой находится код шорткода например: magic(); // Запускатся функция magic, и в ней уже выполняются все колбэк-фукнции которые вы добавили на хуки before_magic и after_magic.

    Таким образом 1-й и 2-й плагины и тема могу взаимодействовать и влиять на код, который находится на какой-то странице или скрыт где-то на бэкенде. Правда круто?

    Список фукнций, относящихся к хукам

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

    Фукнции запускающие колбэки, которые были добавлены на хук (найболее используемые):

    • do_action
    • apply_filters

    Фукнции запускающие колбэки, которые были добавлены на хук с несколькими аргументами, которые переданные по ссылкеp:

    • do_action_ref_array
    • apply_filters_ref_array

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

    • do_action_deprecated
    • apply_filters_deprecated

    Добавить колбэк на хук (найболее используемые):

    Удалить колбэк с хука:

    • remove_action
    • remove_filter

    Удалить все колбэки с хука:

    • remove_all_actions
    • remove_all_filters

    Получить кол-во раз, которые этот хук был вызван за текущий запрос:

    Проверить, добавлен ли колбэк на текущий хук:

    Получить имя текущего хука:

    • current_action
    • current_filter

    Обрабатывается ли в данный момент хук:

    • doing_action
    • doing_filter

    Что же такое колбэк?

    Я думаю в ходе статьи вы уже устали от слова колбэк. Давайте разберемся, что это такое и почему это так важно для хуков? Итак, Callbale — это псевдотип в PHP. Так как нам нужно запускать наш код не сразу, а в какой-то определенный момент, мы должны дать всю нужную информцию о том, что конкретно нам нужно выполнить. Строку add_action( ‘save_post’, ‘notify_administrator’ ); мы должны читать как «на действие сохранения поста вызвать функцию оповещения администратора». Еще раз повторю, потому что это очень важно, мы ничего не вызываем, мы отвечаем на вопросы «Когда?» и «Что нужно запустить?».

    В двух словах тип callable — это то, что мы можем запустить. И что же мы можем запустить в PHP? Мы можем запустить функции или публичные методы объекта или класса, но как из этого сделать callback? Просто передать названия метода или функции. Очень сильно рекомендую вам выучить и разобраться в синтаксисе, потому что разработчики WordPress работает с колбэками каждый день:

    function do_something_awesome() < // . >/** * 1. Имя функции. */ is_callable( 'do_something_awesome' ); // true class Awesome < public static function do_something() < // . >public function do_something_more() < >/** * 4. Методы внутри другого метода. */ public function hooks() < is_callable( [ $this, 'do_something' ] ); // true is_callable( [ $this, 'do_something_more' ] ); // true is_callable( [ __CLASS__, 'do_something' ] ); // true is_callable( 'self::do_something_more' ); // true >public function __invoke( . $values ) < >> $awesome = new Awesome(); $awesome->hooks(); /** * 2. Имя статического метода. */ is_callable( 'Awesome::do_something' ); // true is_callable( [ 'Awesome', 'do_something' ] ) ; // true is_callable( [ Awesome::class, 'do_something' ] ); // true is_callable( [ $awesome, 'do_something' ] ); // true /** * 3. Имя метода объекта $awesome. */ is_callable( [ $awesome, 'do_something_more' ] ); // true /** * 4. Если класс имеет __invoke метод, значит мы можем вызвать класс, как функцию - значит сам объект является колбэком. */ is_callable( $awesome ); // true /** * 5. Анонимная функция. */ is_callable( function () < // true >);

    Посмотрели код? Теперь вернитесь и посмотрите еще раз. Советую выучить синтаксис и уметь понимать его автоматически при чтении кода, потому что колбэки — это основной механизм хуков и еще многих других вещей в WordPress.

    Настройка PhpStorm для хуков

    Настройка PHP интерпретатора и добавление путей проекта

    PHP Настройки для WordPress хуков в PhpStorm

    1. В меню Настройки, перейдите в PHP.
    2. Выберите PHP интерпретатор.
    3. В Включающие пути поле добавте путь, с установкой WordPress. Эта папка должна включать в себя wp-admin и wp-includes подпапки.

    Настройка WordPress как фреймворка

    Настройки WordPress как фреймворка в PhpStorm

    1. В меню Настройки, перейдите в PHP | Frameworks.
    2. На странице найдите WordPress и отметьте чекбокс Включить интеграцию с WordPress.
    3. В поле Путь установки WordPress укажите путь корня установки WordPress. Это папка, которая содержит wp-admin и wp-includes подпапки.
    4. Нажми Применить чтобы сохранить настройки.

    Результат настройки PhpStorm

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

    Автодополнение WordPress хуков в PhpStorm.

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

    Быстрый поиск WordPress хуков в PhpStorm

    Как раставить хуки?

    Если вы пишите тему или плагин для массового использования, то вы обязательно должны оставить как можно больше хуков. Как это сделать правильно? На самом деле тема довольно сложна, потому что каждый случай уникальный, но я все же попробую:

    1. Не жадничайте и оставьте как можно больше хуков, чем их больше, тем легче добавить что-то в ваш код. Я уверен, что другие разработчики еще не раз вам скажут спасибо ��
    2. Добавляйте фильтры для «мистических» чисел, строк, или массивов. Например:
      1. время жизни кеша (мистическое число).
      2. аргументы для получение списка CPT через WP_Query (магический массив)

      Давайте рассмотрим на примере просто запроса в API:

      class API < const URL = 'https://random-data-api.com/api/code/random_code'; public function get_data() < $response = wp_remote_request( self::URL, [ 'method' =>'GET', 'timeout' => 2, ] ); $body = wp_remote_retrieve_body( $response ); if ( is_wp_error( $body ) ) < return []; >$body = json_decode( $body, true ); if ( ! is_array( $body ) || empty( $body ) ) < return []; >return $body; > >
      class API < const URL = 'https://random-data-api.com/api/code/random_code'; public function get_data() < do_action( 'hooks_api_before_request' ); $response = wp_remote_request( self::URL, $this->get_request_arguments() ); $body = $this->get_response_body( $response ); do_action( 'hooks_api_after_request', $response ); return apply_filters( 'hooks_api_get_data', $body ); > private function get_response_body( $response ) < if ( is_wp_error( $response ) ) < return apply_filters( 'hooks_api_fail_request', [], $response ); >$body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( ! $this->is_valid_body( $body ) ) < return apply_filters( 'hooks_api_fail_request', [], $response ); >return $body; > private function is_valid_body( $body ) < return apply_filters( 'hooks_api_is_valid_body', is_array( $body ) && ! empty( $body ), $body ); >private function get_request_arguments() < return apply_filters( 'hooks_api_get_request_arguments', [ 'method' =>'GET', 'timeout' => 2, ] ); > >
      • hooks_api_before_request — Разрешаем делать что-нибудь до отправки запроса в API.
      • hooks_api_after_request — Разрешаем делать что-нибудь после отправки запроса в API.
      • hooks_api_get_request_arguments — Расрешаем изменять аргументы запроса, такие как timeout, headers, и т.д.
      • hooks_api_fail_request — Разрешаем изменить неудачный ответ, например мы можем вернуть какие-то данные по умолчанию.
      • hooks_api_is_valid_body — Разрешает проверить валидность ответа из API.
      • hooks_api_get_data — Расрешает изменить результат, который вы получили из API.

      И еще один пример, шорткод, который печатает какую-то таблицу:

      add_shortcode( 'dummy_table', 'dummy_table' ); function dummy_table( $attributes ) < $api = new API(); $table_data = $api->get_data(); echo '
      '; > echo '
      '; echo '
    '; >
    add_shortcode( 'dummy_table', 'dummy_table' ); function dummy_table( $attributes ) < $api = new API(); $table_data = $api->get_data(); $attributes = apply_filters( 'dummy_table_attributes', $attributes ); $table_data = apply_filters( 'dummy_table_data', $table_data, $attributes ); $wrapper_classes = apply_filters( 'dummy_table_wrapper_classes', [ 'dummy-table-wrapper' ], $table_data, $attributes ); $table_classes = apply_filters( 'dummy_table_classes', [ 'dummy-table' ], $table_data, $attributes ); $row_classes = [ 'dummy-table-row' ]; do_action( 'dummy_table_before', $table_data, $attributes ); printf( '
    '; > echo '
    '; do_action( 'dummy_table_before_wrapper_close', $table_data, $attributes ); echo '
    '; do_action( 'dummy_table_after', $table_data, $attributes ); >

    Соглашение об именовании хуков

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

    Для примера вы можете использовать Полное название класса (FQCN) + название метода + дополнительная инфорация(опционально). Давайте обновим наш код для запроса в API с помощью этого соглашения:

    namespace WPPunk\Hooks; class API < const URL = 'https://random-data-api.com/api/code/random_code'; public function get_data() < $body = $this->make_request(); return apply_filters( 'wp_punk_hooks_api_get_data', $body ); > private function make_request() < do_action( 'wp_punk_hooks_api_make_request_before' ); $response = wp_remote_request( self::URL, $this->get_request_arguments() ); $body = $this->get_response_body( $response ); do_action( 'wp_punk_hooks_api_make_request_after', $response ); return $body; > private function get_response_body( $response ) < if ( is_wp_error( $response ) ) < return $this->fail_request( $response ); > $body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( ! $this->is_valid_body( $body ) ) < return $this->fail_request( $response ); > return $body; > private function fail_request( $response ) < return apply_filters( 'wp_punk_hooks_api_fail_request', [], $response ); >private function is_valid_body( $body ) < return apply_filters( 'wp_punk_hooks_api_is_valid_body', is_array( $body ) && ! empty( $body ), $body ); >private function get_request_arguments() < return apply_filters( 'wp_punk_hooks_api_get_request_arguments', [ 'method' =>'GET', 'timeout' => 2, ] ); > >

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

    Так же в документации WordPress есть еще один интересный момент на тему именования хуков — это использовать фигурные скобки для динамических мест и не использовать оператор конкатинации( . ):

    do_action( "_post_type>", $post->ID, $post );
    do_action( $new_status . '_' . $post->post_type, $post->ID, $post );

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

    На этом у меня все. Удачно похукать ��

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *