Вопрос или проблема
Я создаю что-то для клиента, и у меня есть класс, который я создал с пользовательским типом записи под названием ‘PuSH Feeds’. Когда пользователь добавляет новую запись и публикует ее, он может нажать на одну из двух кнопок, которые у меня есть в настраиваемом мета-боксе.
Одна кнопка предназначена для ‘Подписки’, а другая – для ‘Отписки’. Я использую хук действия save_post и проверяю, имеет ли глобальная переменная $_POST значение ‘pushfeed-subscribe’ или ‘pushfeed-unsubscribe’, и затем выполняю необходимые действия. Однако по какой-то причине я обнаружил, что после нажатия на подписку на моем локальном компьютере скрипт останавливается из-за 100 последовательных вызовов и т. д., и в итоге я получаю множество дублирующих записей без заголовка.
Какой был бы лучший способ избежать этого, и есть ли лучший хук, который я могу использовать для этих специальных пользовательских действий, которые я хочу активировать для подписки на фид (что переходит в другой класс и выполняет метод подписки)?
Это разметка, которую я использую для тех двух кнопок, о которых я упоминал, которые находятся внутри мета-бокса:
<input type="submit" class="button-secondary" name="pushfeed-subscribe" id="pushfeed-subscribe" value="Subscribe">
<input type="submit" class="button-secondary" name="pushfeed-unsubscribe" id="pushfeed-unsubscribe" value="Unsubscribe">
Затем у меня есть это для хука действия:
add_action( 'save_post', array( $this, 'pushfeed_save_post_meta' ) );
Сам хук выглядит так:
public function pushfeed_save_post_meta( $post_id ) {
// Выход, если происходит автоматическое сохранение
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
// если наш nonce отсутствует или мы не можем его проверить, выходим
if( !isset( $_POST['pushfeed-nonce-field'] ) || !wp_verify_nonce( $_POST['pushfeed-nonce-field'], basename( __FILE__ ) ) ) return;
// Если идентификатор подписки пуст, создадим случайное длинное число и сохраним его
if ( empty( $_POST['pushfeed-subscription-id'] ) ) {
$random_number = substr(number_format(time() * mt_rand(),0,'',''),0,10);
$pushfeed_subscription_id = $random_number . $post_id;
update_post_meta( $post_id, 'pushfeed-subscription-id', $pushfeed_subscription_id );
}
...
if ( isset( $_POST['pushfeed-subscribe'] ) || isset( $_POST['pushfeed-unsubscribe'] ) ) {
$subscription_domain = get_post_meta($post_id, 'pushfeed-domain', true);
$subscription_id = get_post_meta($post_id, 'pushfeed-subscription-id', true);
$subscription_feed_url = get_post_meta($post_id, 'pushfeed-feed-url', true);
$subscription_callback_url = $subscription_domain . '/pushfeed/' . $subscription_id;
$sub = PuSHSubscriber::instance($subscription_domain, $subscription_id, 'PuSHSubscription', new PuSHEnvironment());
if ( isset( $_POST['pushfeed-subscribe'] ) ) {
$sub->subscribe($subscription_feed_url, $subscription_callback_url);
} elseif ( isset( $_POST['pushfeed-unsubscribe'] ) ) {
$sub->unsubscribe($subscription_feed_url, $subscription_callback_url);
}
}
}
Я пытаюсь выяснить, почему запись сохраняется с несколькими дубликатами без заголовка.
Но прежде всего я хотел бы знать, есть ли лучший хук действия, который я могу вызвать для этих двух пользовательских действий.
Обновление :
Всем привет. Я в итоге использовал Ajax-запрос с помощью wordpress admin-ajax.php при нажатии кнопки, а затем выполнял метод подписки. После этого метод подписки выполняет GET-запрос, и, если он возвращает код 200, метод возвращает true в Ajax.
Не уверен, если это точно та проблема, которую вы имеете, но похоже, что хук ‘save_post’ зацикливается.
Вам нужно отключить хук, выполнить обновления, а затем подключить его снова.
{
remove_action('save_post', array( $this, 'pushfeed_save_post_meta' ));
// Выполните работу по обновлению...
add_action('save_post', array( $this, 'pushfeed_save_post_meta' ));
}
Ответ или решение
Создание кастомных кнопок для выполнения нестандартных действий на экране редактирования поста в WordPress требует особенно тщательного подхода, учитывая вашу ситуацию с пользовательскими действиями "Подписаться" и "Отписаться". Мы столкнулись с проблемой рекурсивного вызова хука save_post
, что привело к созданию многочисленных дубликатов постов без заголовка. Рассмотрим лучшие практики и решения для этой задачи.
Краткий контекст и задача
В рамках вашего проекта для клиента, вы создали кастомный тип записи "PuSH Feeds" и добавили кастомную метабокс, содержащую две кнопки для подписки и отписки. Ваш текущий подход использует хук save_post
, который может быть не лучшим выбором из-за рискованного поведения и возникновения рекурсивных вызовов.
Решения
-
Использование AJAX для обработки пользовательских действий
Вместо использования хука
save_post
, рекомендуется обрабатывать действия "Подписаться" и "Отписаться" с помощью AJAX. Этот подход минимизирует риск рекурсии и позволяет напрямую взаимодействовать с функциями вашего класса, отправляя асинхронные запросы к серверу. Процедура выглядит следующим образом:- Создайте JavaScript, который будет слушать нажатия кнопок и отправлять AJAX-запросы к обработчикам на стороне сервера.
- В
functions.php
зарегистрируйте AJAX-обработчики черезadd_action('wp_ajax_ВАШЕ_ДЕЙСТВИЕ', 'callback_function')
. - В коллбэк-функциях выполните подписку или отписку, возвращая соответствующий ответ клиенту.
-
Защита от рекурсии
Если все же необходимо оставить логику в хук
save_post
, убедитесь в предотвращении рекурсии:-
Отключение хуков: временно удаляйте хук перед обновлением данных и возвращайте его после завершения функции.
remove_action('save_post', array($this, 'pushfeed_save_post_meta')); // Выполнение действий... add_action('save_post', array($this, 'pushfeed_save_post_meta'));
-
Проверка состояний поста: добавляйте проверки на изменение содержимого и статуса публикации, чтобы избежать ненужных срабатываний функции.
-
Использование транзитных данных: для предотвращения повторных вызовов, храните временные данные о выполнении действий в транзиентах или других безопасных местах хранения.
-
-
Обеспечение корректной работы с мета-данными
Если вы оставляете обработку внутри
save_post
, допускать минимальное количество операций и уделить внимание валидации данных, получаемых из$_POST
. Обязательно выполняйте проверку nonce-поля и валидацию данных перед их использованием.
Подводя итог
Работа с нестандартными действиями в WordPress требует внимательного выбора хуков и инструментов для реализации. Используйте AJAX для уменьшения зависимости от тяжёлой серверной логики, и избегайте рекурсивных вызовов. Подход с поверкой состояния системы и временным отключением хука поможет избежать проблем и улучшить производительность.
Надеемся, что данное решение окажется полезным для вашего проекта. Успехов в разработке!