Почему срабатывает действие save_post при создании новой записи?
Я удивлён тем, что моя функция, подключённая к действию save_post
, срабатывает при клике на ссылку "Новая запись" в админ-панели WordPress. Примечание - это происходит до нажатия кнопок Сохранить или Обновить, и срабатывает мгновенно, а не после какого-то времени или автосохранения.
С другой стороны, когда я ввожу текст и нажимаю кнопки Опубликовать, Обновить или Сохранить черновик, echo-вывод, который я добавил в обработчик действия, не появляется, что указывает на то, что действие НЕ срабатывает в этих случаях. Возможно, это не связано.
Вот мой код:
add_action('save_post', 'MyNS\save_event_metabox', 10, 2);
function save_event_metabox($post_id, $post){
echo "<h1>ДА!</h1>";
}
Это "ДА!" выводится (в верхней части страницы) при нажатии на "Новая запись", но НЕ выводится при вводе текста и последующем нажатии Обновить, Опубликовать или Сохранить черновик. Это кажется противоречащим документации по действию save_post
и функции wp_insert_post()
.
Может кто-нибудь прояснить эту ситуацию?

При нажатии на кнопку "Новая запись" загружается страница wp-admin/post-new.php
.
При этом WordPress всегда создает новую запись ("Автосохраненный черновик"), чтобы обеспечить корректную работу всех остальных функций (например, загрузки медиафайлов) и плагинов, даже до того, как вы сохраните черновик или опубликуете запись.
Это, в свою очередь, вызывает срабатывание хука save_post
. Отсюда и ваше сообщение через echo.
Хорошо, но почему тогда я не вижу сообщения при обновлении или публикации?
Между сохранением и последующей загрузкой страницы WordPress фактически отправляет GET
-редирект обратно на ту же страницу, который выглядит прозрачным (это можно наблюдать с помощью монитора HTTP-запросов, например HttpFox).
Другими словами:
- Вы нажимаете
Обновить
илиОпубликовать
- Браузер отправляет данные на сервер
- WordPress обрабатывает их, в процессе срабатывает хук
save_post
- WordPress отправляет обратно заголовок редиректа и завершает работу до появления какого-либо вывода в браузере (включая ваш echo)*
- Браузер следует редиректу и загружает страницу редактирования записи.
Редирект может показаться излишним (ведь можно просто отправить POST
на ту же страницу), но это часть техники, известной как Post/Redirect/Get, которая позволяет избежать повторной отправки форм.
Если вы пытаетесь выводить пользовательские сообщения на основе результата функции, подключенной к хуку save_post
, ознакомьтесь с этими вопросами и ответами.
*Строго говоря, ваш echo на самом деле произойдет до отправки заголовка редиректа, но браузер либо проигнорирует его, либо все происходит настолько быстро, что он никогда не отображается.

Потрясающе. Спасибо за такой полный и детальный ответ! Чтобы узнать больше, расскажи, как ты впервые нашел эту информацию?

Через такое же разочарование, которое испытывал ты ;) Возьми хорошую IDE (я использую phpDesigner) и просто погрузись в соответствующие административные файлы.

Отличная информация. Я сходил с ума, потому что на локальном сервере всё вроде работало "нормально", но не на продакшн-сервере... Похоже, на локальном сервере метод post/redirect/get не применялся правильно, так как не отправлялся заголовок перенаправления (хотя не знаю, почему).

Спасибо за ответ. Я надеялся использовать параметр $update, чтобы определить, было ли событие сохранения первым или обновлением, но узнал, что все ручные сохранения будут иметь $update как true. Так ли это? Интересно, есть ли элегантное решение без сравнения статусов записи, которые могут быть динамичными. (Пока это мой любимый ответ: https://wordpress.stackexchange.com/a/365727/2798)
