Указатель хуков WordPress
Поисковый указатель действий и фильтров WordPress, которыми разработчики действительно пользуются, — с точной сигнатурой add_action/add_filter, моментом срабатывания, рабочим примером и тем, на чём люди обжигаются.
39 хуков — с точной сигнатурой add_action / add_filter, моментом срабатывания, рабочим примером и тем, на чём обычно спотыкаются. 1 помечены как непроверенные — мы не сверяли количество их аргументов с исходным кодом WordPress и предпочли отметить это, а не выдавать догадку за факт.
Список не исчерпывающий и не претендует на это — в WordPress тысячи хуков. Здесь собраны те, к которым действительно обращаются на практике.
Запускается после того, как WordPress завершил загрузку, но до отправки каких-либо заголовков. Стандартное место для регистрации пользовательских типов записей, таксономий и правил перезаписи.
Срабатывает
На каждом запросе — и на фронтенде, и в админке — после загрузки ядра, плагинов и темы.
Сигнатура
add_action( 'init', 'my_callback' );Пример
add_action( 'init', function () {
register_post_type( 'book', array(
'public' => true,
'label' => 'Books',
'show_in_rest' => true, // required for the block editor
) );
} );Подвох
init выполняется на КАЖДОМ запросе, включая AJAX, REST и cron. Любая медленная операция здесь (HTTP-запрос, тяжёлый запрос к БД) нагружает каждую загрузку страницы. Кроме того: текущий пользователь здесь уже доступен, но выводить что-либо нельзя — заголовки ещё не отправлены, но вот-вот будут.
Запускается сразу после загрузки темы. Правильное место для add_theme_support(), add_image_size() и регистрации меню навигации.
Срабатывает
После загрузки functions.php темы, ДО init.
Сигнатура
add_action( 'after_setup_theme', 'my_callback' );Пример
add_action( 'after_setup_theme', function () {
add_theme_support( 'post-thumbnails' );
add_theme_support( 'title-tag' );
add_image_size( 'card', 600, 400, true ); // true = hard crop
} );Подвох
Регистрация размеров изображений на init вместо этого хука в большинстве случаев срабатывает по случайности, а иногда загадочным образом ломается. Используйте after_setup_theme — он именно для этого.
Запускается после загрузки всех активных плагинов. Самая ранняя безопасная точка для взаимодействия с другим плагином.
Срабатывает
После подключения всех файлов плагинов, до загрузки темы.
Сигнатура
add_action( 'plugins_loaded', 'my_callback' );Подвох
Текущий пользователь здесь ещё НЕ доступен — wp_get_current_user() не будет работать надёжно. Если нужен пользователь, используйте init.
Запускается после полной загрузки WordPress — плагины, тема, init и пользователь уже готовы.
Срабатывает
После init и после инициализации текущего пользователя.
Сигнатура
add_action( 'wp_loaded', 'my_callback' );Запускается в начале каждого запроса к админке. Используется для register_setting(), проверок прав доступа и перенаправлений в админке.
Срабатывает
На каждом запросе со стороны админки.
Сигнатура
add_action( 'admin_init', 'my_callback' );Подвох
Он также срабатывает на запросах к admin-ajax.php, которые на самом деле не являются «экранами админки». Если ваш колбэк предполагает наличие экрана, защитите его проверкой wp_doing_ajax().
Единственное правильное место для подключения CSS и JavaScript на фронтенде.
Срабатывает
При загрузке страниц фронтенда, до отрисовки <head>.
Сигнатура
add_action( 'wp_enqueue_scripts', 'my_callback' );Пример
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style(
'child-style',
get_stylesheet_uri(),
array( 'parent-style' ), // load AFTER the parent
wp_get_theme()->get( 'Version' ) // cache-bust on version change
);
} );Подвох
Несмотря на название, он отвечает не только за скрипты, но и за СТИЛИ — хука wp_enqueue_styles не существует, и люди реально тратят время на его поиски. Кроме того: он не срабатывает в админке (используйте admin_enqueue_scripts) и в блочном редакторе (используйте enqueue_block_editor_assets).
Подключение CSS/JS в админке. Получает суффикс хука текущего экрана, поэтому вы можете загружать ресурсы только на одном экране.
Срабатывает
При загрузке страниц админки.
Сигнатура
add_action( 'admin_enqueue_scripts', 'my_callback' ); // receives $hook_suffixПример
add_action( 'admin_enqueue_scripts', function ( $hook ) {
if ( 'settings_page_my-plugin' !== $hook ) {
return; // do not load our JS on every admin screen
}
wp_enqueue_script( 'my-admin', plugins_url( 'admin.js', __FILE__ ), array(), '1.0', true );
} );Подвох
Отсутствие проверки $hook — самая частая причина, по которой плагин ломает не связанные с ним экраны админки. Загружайте ресурсы там, где они нужны, и больше нигде.
Подключение ресурсов только в блочном редакторе (Gutenberg) — не на фронтенде и не в остальной админке.
Срабатывает
При загрузке блочного редактора.
Сигнатура
add_action( 'enqueue_block_editor_assets', 'my_callback' );Выводит содержимое в <head>. Используется для мета-тегов и встроенного критического CSS.
Срабатывает
Внутри <head>, на фронтенде.
Сигнатура
add_action( 'wp_head', 'my_callback' );Подвох
НЕ подключайте здесь скрипты или стили — используйте wp_enqueue_scripts, который позволяет WordPress управлять зависимостями и устранять дубли. Вывод тега <script> прямо в wp_head обходит всё это и является причиной, по которой столько сайтов загружают jQuery по три раза.
Выводит содержимое прямо перед </body>. Подходящее место для сниппетов аналитики и отложенной разметки.
Срабатывает
В конце страницы фронтенда.
Сигнатура
add_action( 'wp_footer', 'my_callback' );Подвох
Тема, забывшая вызвать wp_footer(), ломает панель администратора, ломает любой плагин, подключающий скрипт в футере, и автоматически отклоняется при проверке тем на wordpress.org.
Фильтрует содержимое записи прямо перед его отображением. Обычное место, чтобы добавить разметку до или после записи.
Срабатывает
Каждый раз при вызове the_content().
Сигнатура
add_filter( 'the_content', 'my_callback' ); // receives $contentПример
add_filter( 'the_content', function ( $content ) {
if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
return $content; // <- the guard everyone forgets
}
return $content . '<p class="cta">Enjoyed this? Read more.</p>';
} );Подвох
Он выполняется гораздо чаще, чем кажется — в виджетах, в REST-ответах, при генерации отрывков некоторыми плагинами и по разу на запись в цикле на архивной странице. Без проверки is_singular / in_the_loop / is_main_query ваш призыв к действию появится пятнадцать раз на главной странице блога и внутри RSS-ленты. Это самый неправильно используемый фильтр в WordPress.
Фильтрует заголовок записи перед отображением.
Срабатывает
Каждый раз при вызове the_title() или get_the_title().
Сигнатура
add_filter( 'the_title', 'my_callback', 10, 2 ); // receives $title, $post_idПодвох
Он также срабатывает для заголовков в меню админки, в меню навигации и в <title> документа. Безусловная фильтрация переименует вещи в тех местах, где вы этого не планировали.
Задаёт, сколько СЛОВ содержит автоматически сгенерированный отрывок. По умолчанию — 55.
Срабатывает
Когда WordPress генерирует отрывок для записи без вручную заданного отрывка.
Сигнатура
add_filter( 'excerpt_length', 'my_callback' ); // receives $length (words)Пример
add_filter( 'excerpt_length', function ( $length ) {
return 25;
}, 999 ); // high priority: many themes set this too, and last one winsПодвох
Он не влияет на записи с РУЧНЫМ отрывком — такие используются дословно. К тому же многие темы задают этот фильтр сами, поэтому часто нужен высокий номер приоритета, чтобы победить.
Меняет строку, добавляемую к обрезанному отрывку. По умолчанию — " […]".
Срабатывает
Когда автоматически сгенерированный отрывок обрезается.
Сигнатура
add_filter( 'excerpt_more', 'my_callback' ); // receives $moreИзменяет запрос ДО его выполнения. Правильный способ поменять то, что отображается на архивной странице, — намного лучше, чем второй WP_Query.
Срабатывает
После разбора переменных запроса, до построения SQL.
Сигнатура
add_action( 'pre_get_posts', 'my_callback' ); // receives WP_Query $query (by reference)Пример
add_action( 'pre_get_posts', function ( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return; // <- both guards are mandatory
}
if ( $query->is_category() ) {
$query->set( 'posts_per_page', 12 );
}
} );Подвох
Он выполняется и в АДМИНКЕ, и для КАЖДОГО запроса, включая меню, виджеты и медиатеку. Пропустите проверки is_admin() и is_main_query() — и вы незаметно измените то, что показывает список записей в админке, а такую ошибку по-настоящему трудно отследить. Также учтите: изменяйте $query, ничего не возвращайте.
Фильтрует сырое SQL-условие WHERE запроса.
Срабатывает
Во время сборки SQL запроса.
Сигнатура
add_filter( 'posts_where', 'my_callback', 10, 2 ); // receives $where, WP_Query $queryПодвох
Вы пишете сырой SQL. Всегда защищайтесь проверкой $query->is_main_query() и всегда используйте $wpdb->prepare() для любых пользовательских данных. Это самый быстрый способ занести SQL-инъекцию на сайт WordPress.
Фильтрует общее число записей, найденных запросом, — именно из него рассчитывается пагинация.
Срабатывает
После выполнения запроса, до вычисления пагинации.
Сигнатура
add_filter( 'found_posts', 'my_callback', 10, 2 ); // receives $found_posts, WP_Query $queryЗадаёт размер в пикселях, выше которого WordPress уменьшает загружаемое изображение и отдаёт копию «-scaled» вместо вашего оригинала. По умолчанию — 2560.
Срабатывает
При загрузке, когда WordPress решает, является ли изображение «большим».
Сигнатура
add_filter( 'big_image_size_threshold', 'my_callback' ); // receives int $thresholdПример
// Serve originals at full resolution — no -scaled copy.
add_filter( 'big_image_size_threshold', '__return_false' );
// Or just raise the ceiling:
add_filter( 'big_image_size_threshold', function () {
return 3840;
} );Подвох
Это самая частая причина жалоб «моё изображение выглядит размытым после загрузки в WordPress», и почти никто не знает о его существовании. Ваш оригинал по-прежнему лежит на диске — его просто никогда не отдают. Учтите: он применяется к САМОЙ ДЛИННОЙ стороне и влияет только на изображения, загруженные после активации фильтра.
Фильтрует массив размеров изображений, которые WordPress собирается сгенерировать для загрузки. Удалите размер из массива, чтобы прекратить его генерацию.
Срабатывает
При загрузке, до создания производных файлов.
Сигнатура
add_filter( 'intermediate_image_sizes_advanced', 'my_callback', 10, 2 ); // receives $sizes, $metadataПример
add_filter( 'intermediate_image_sizes_advanced', function ( $sizes ) {
unset( $sizes['1536x1536'] );
unset( $sizes['2048x2048'] );
return $sizes;
} );Подвох
Удаление размера, который ваша тема реально ИСПОЛЬЗУЕТ, приводит к тому, что WordPress откатывается к полноразмерному оригиналу — а это хуже, чем сэкономленное место на диске. И это останавливает создание только НОВЫХ файлов; существующие остаются, пока вы не перегенерируете их.
Задаёт качество JPEG, с которым WordPress перекодирует загруженные изображения. По умолчанию — 82.
Срабатывает
Каждый раз, когда WordPress записывает JPEG.
Сигнатура
add_filter( 'jpeg_quality', 'my_callback', 10, 2 ); // receives $quality, $contextПодвох
Качество 82 нормально для фотографий и заметно плохо для скриншотов, логотипов и плоской графики — у них резкие края и нет фотографического шума, за которым можно спрятать артефакты. Кроме того: wp_editor_set_quality — более современный фильтр, который напрямую охватывает классы редактора изображений; часто задают оба.
Задаёт выходное качество, используемое классами WP_Image_Editor (GD и Imagick).
Срабатывает
Когда экземпляр редактора изображений устанавливает своё качество.
Сигнатура
add_filter( 'wp_editor_set_quality', 'my_callback', 10, 2 ); // receives $quality, $mime_typeДобавляет ваши пользовательские размеры изображений в выпадающий список размеров в медиа-окне и блочном редакторе.
Срабатывает
Когда интерфейс медиа строит свой селектор размеров.
Сигнатура
add_filter( 'image_size_names_choose', 'my_callback' ); // receives $sizesПример
add_filter( 'image_size_names_choose', function ( $sizes ) {
return array_merge( $sizes, array( 'card' => __( 'Card', 'textdomain' ) ) );
} );Подвох
add_image_size() регистрирует размер, но НЕ делает его выбираемым в редакторе. За каждым вопросом «мой пользовательский размер изображения не появляется в выпадающем списке» стоит отсутствие этого фильтра.
Проверяет или отклоняет файл ДО его перемещения в папку загрузок.
Срабатывает
Во время загрузки, до записи файла.
Сигнатура
add_filter( 'wp_handle_upload_prefilter', 'my_callback' ); // receives $fileПодвох
Чтобы отклонить файл, задайте $file['error'] строкой с сообщением и верните $file. Возврат false или выброс исключения не сделают того, что вам нужно.
Фильтрует массив метаданных (включая сгенерированные размеры) после обработки вложения.
Срабатывает
После создания производных изображений при загрузке.
Сигнатура
add_filter( 'wp_generate_attachment_metadata', 'my_callback', 10, 2 ); // receives $metadata, $attachment_idПодвох
Этот хук используют плагины оптимизации изображений. Он может быть медленным — выполняется после записи каждого размера изображения, и HTTP-запрос здесь заставляет каждую загрузку ждать его завершения.
Фильтрует кандидатов srcset, которые WordPress генерирует для адаптивного изображения.
Срабатывает
Когда отрисовывается адаптивное изображение.
Сигнатура
add_filter( 'wp_calculate_image_srcset', 'my_callback', 10, 5 );Подвох
Удаление размера medium_large (768w) в другом месте незаметно ухудшает srcset — этот размер существует почти исключительно ради него.
Мы не сверяли точное количество аргументов этого хука с исходным кодом WordPress. Прежде чем полагаться на него, проверьте developer.wordpress.org. Мы предпочитаем обозначить неопределённость, а не молча выдавать догадку за факт.
Регистрирует страницы меню и подменю в админке.
Срабатывает
Когда строится меню админки.
Сигнатура
add_action( 'admin_menu', 'my_callback' );Пример
add_action( 'admin_menu', function () {
add_options_page(
'My Plugin',
'My Plugin',
'manage_options', // capability — NOT a role
'my-plugin',
'my_render_settings_page'
);
} );Подвох
Аргумент возможности — это ВОЗМОЖНОСТЬ (capability), а не роль. Передача «administrator» вроде бы работает (потому что в некоторых конфигурациях у админов есть возможность с таким именем), а затем тихо открывает доступ не тем людям. Используйте manage_options.
Выводит уведомление вверху экрана админки.
Срабатывает
При отрисовке страницы админки.
Сигнатура
add_action( 'admin_notices', 'my_callback' );Подвох
Он срабатывает на КАЖДОМ экране админки. Плагин, который безусловно показывает уведомление «спасибо за установку!» на всех из них, — самый ненавидимый паттерн в админке WordPress. Ограничьте его условием и сделайте закрываемым.
Запускается всякий раз, когда запись создаётся или обновляется. Обычное место для сохранения данных метабокса.
Срабатывает
После записи поста в базу данных.
Сигнатура
add_action( 'save_post', 'my_callback', 10, 3 ); // receives $post_id, $post, $updateПример
add_action( 'save_post', function ( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( wp_is_post_revision( $post_id ) ) return;
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
// ... now it is safe to save
}, 10, 1 );Подвох
Он срабатывает при АВТОСОХРАНЕНИЯХ и РЕВИЗИЯХ, а не только при настоящих сохранениях. Без трёх проверок, указанных выше, ваши метаданные перезаписываются пустыми значениями каждый раз, когда редактор выполняет автосохранение, — ошибка выглядит так, будто данные случайно пропадают.
Регистрирует метабоксы на экране редактирования записи.
Срабатывает
Когда строится экран редактирования.
Сигнатура
add_action( 'add_meta_boxes', 'my_callback', 10, 2 ); // receives $post_type, $postПодвох
Классические метабоксы не отображаются в блочном редакторе, если только он не переключается в режим совместимости. Для сайта, изначально работающего в блочном редакторе, регистрируйте мета-поля записи с show_in_rest и вместо этого создавайте панель в боковой колонке.
Запускается после успешного входа пользователя.
Срабатывает
При успешной аутентификации.
Сигнатура
add_action( 'wp_login', 'my_callback', 10, 2 ); // receives $user_login, WP_User $userЗапускается сразу после создания нового пользователя.
Срабатывает
При регистрации.
Сигнатура
add_action( 'user_register', 'my_callback', 10, 2 ); // receives $user_id, $userdataФильтрует результат аутентификации. Верните WP_Error, чтобы заблокировать вход.
Срабатывает
Во время попытки входа.
Сигнатура
add_filter( 'authenticate', 'my_callback', 30, 3 ); // receives $user, $username, $passwordПодвох
Здесь приоритет очень важен. Ядро WordPress вешает собственные проверки на приоритеты 20 и 30 — привяжетесь слишком рано, и ваш код выполнится ещё до проверки пароля.
Регистрирует REST-маршруты и поля.
Срабатывает
Когда инициализируется REST API.
Сигнатура
add_action( 'rest_api_init', 'my_callback' );Пример
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/items', array(
'methods' => 'GET',
'callback' => 'my_get_items',
'permission_callback' => '__return_true', // BE DELIBERATE ABOUT THIS
) );
} );Подвох
permission_callback ОБЯЗАТЕЛЕН — начиная с WP 5.5 его отсутствие вызывает предупреждение, а установка в __return_true делает эндпоинт полностью публичным. Это нормально для действительно публичных данных и серьёзная дыра для всего остального. Принимайте решение осознанно, а не оставляйте по умолчанию.
Добавляет пользовательский интервал повторения для wp_schedule_event().
Срабатывает
Когда WordPress строит список доступных расписаний.
Сигнатура
add_filter( 'cron_schedules', 'my_callback' ); // receives $schedulesПример
add_filter( 'cron_schedules', function ( $schedules ) {
$schedules['every_five_minutes'] = array(
'interval' => 300, // seconds
'display' => __( 'Every 5 minutes', 'textdomain' ),
);
return $schedules;
} );Подвох
WP-Cron — это не настоящий cron. Он срабатывает только когда кто-то заходит на сайт, поэтому сайт с малым трафиком не будет выполнять пятиминутное расписание каждые пять минут. Если тайминг действительно важен, отключите WP-Cron (DISABLE_WP_CRON) и вызывайте wp-cron.php из настоящего системного cron.
Запускается сразу после сохранения комментария.
Срабатывает
При отправке комментария.
Сигнатура
add_action( 'comment_post', 'my_callback', 10, 3 ); // receives $comment_id, $approved, $commentdataФильтрует данные комментария до его сохранения. Используется для проверок на спам и валидации.
Срабатывает
До записи комментария.
Сигнатура
add_filter( 'preprocess_comment', 'my_callback' ); // receives $commentdataПодвох
Чтобы отклонить комментарий здесь, вызовите wp_die() с сообщением — возврат false его не остановит.
Запускается на странице получения заказа после успешного оформления заказа.
Срабатывает
Когда покупатель попадает на страницу благодарности.
Сигнатура
add_action( 'woocommerce_thankyou', 'my_callback' ); // receives $order_idПодвох
Это НЕнадёжное место для запуска обработки заказа. Он срабатывает, только если покупатель действительно дошёл до страницы благодарности — если он закроет вкладку после оплаты, хук не выполнится. Для всего, что должно произойти обязательно, используйте woocommerce_payment_complete или хук смены статуса заказа.
Выводит разметку прямо перед кнопкой добавления в корзину на странице товара.
Срабатывает
Во время отрисовки страницы товара.
Сигнатура
add_action( 'woocommerce_before_add_to_cart_button', 'my_callback' );Добавляет, удаляет или переупорядочивает поля на классическом оформлении заказа.
Срабатывает
Когда строится форма оформления заказа.
Сигнатура
add_filter( 'woocommerce_checkout_fields', 'my_callback' ); // receives $fieldsПодвох
Это влияет только на КЛАССИЧЕСКОЕ оформление заказа (на основе шорткода). Более новое оформление заказа на блоках полностью игнорирует его и настраивается через Slot & Fill в JavaScript. На этом спотыкаются почти все с первого раза.