Что такое хук woocommerce_order_status_changed и зачем он нужен
Хук woocommerce_order_status_changed срабатывает при изменении статуса заказа в WooCommerce. Его часто используют для автоматизации процессов, например, для обновления метаданных заказа, отправки уведомлений или интеграции с внешними сервисами без ручного вмешательства.
Использование этого хука позволяет реагировать на смену статуса, например, при переходе заказа из "в обработке" в "завершён" или при возврате средств.
Диагностика: как понять, что метаданные не обновляются автоматически
- Вы изменили статус заказа, но связанные с ним метаданные остаются прежними.
- Автоматические процессы (например, расчёт бонусов, обновление пользовательских данных) не запускаются.
- Нет ошибок PHP, но нет и ожидаемого результата.
Для диагностики можно добавить временный лог в обработчик хука, чтобы проверить, вызывается ли он:
add_action( 'woocommerce_order_status_changed', 'debug_order_status_change', 10, 4 );
function debug_order_status_change( $order_id, $old_status, $new_status, $order ) {
error_log("Order #$order_id status changed from $old_status to $new_status");
}Если в логах нет сообщений — хук не срабатывает, значит, проблема в регистрации обработчика или конфликте с другими плагинами.
Пошаговое решение: автоматическое обновление метаданных заказа при смене статуса
Рассмотрим пример, где при переходе заказа в статус completed записывается текущее время в мета поле _completed_timestamp.
add_action( 'woocommerce_order_status_changed', 'update_completed_timestamp_meta', 10, 4 );
function update_completed_timestamp_meta( $order_id, $old_status, $new_status, $order ) {
if ( 'completed' === $new_status ) {
update_post_meta( $order_id, '_completed_timestamp', current_time( 'mysql' ) );
}
}Объяснение кода:
- Функция получает ID заказа и новые/старые статусы.
- Проверяем, что новый статус -
completed. - Обновляем мета поле заказов с текущим временем в формате MySQL.
Расширенный пример: добавление кастомного флага и уведомления администратору
add_action( 'woocommerce_order_status_changed', 'custom_order_status_actions', 10, 4 );
function custom_order_status_actions( $order_id, $old_status, $new_status, $order ) {
if ( 'processing' === $new_status ) {
update_post_meta( $order_id, '_custom_flag', 'yes' );
wp_mail(
get_option( 'admin_email' ),
"Order #$order_id changed status to processing",
"Заказ №$order_id перешёл в статус обработка."
);
}
}Как проверить, что решение сработало
- Перейдите в админку WooCommerce → Заказы.
- Измените статус выбранного заказа на
completedилиprocessingв зависимости от примера. - Проверьте значения метаданных заказа через базу данных или с помощью плагина типа Adminer или WP phpMyAdmin.
- Для примера с уведомлением — проверьте почту администратора.
- Также можно вывести значение мета поля в шаблоне заказа, чтобы визуально убедиться в обновлении:
$completed_time = get_post_meta( $order->get_id(), '_completed_timestamp', true );
echo 'Время завершения: ' . esc_html( $completed_time );Частые ошибки при использовании woocommerce_order_status_changed
- Неправильное имя хука или параметров. Хук должен использоваться именно как
woocommerce_order_status_changedс четырьмя аргументами. - Отсутствие приоритета и количества аргументов. При регистрации обработчика нужно указать 4 параметра:
add_action('woocommerce_order_status_changed', 'func', 10, 4). - Ошибки в логике проверки статусов. Например, сравнение с несуществующим статусом, или использование строгого сравнения без учёта регистра.
- Проблемы с правами доступа. Если обработчик изменяет данные, убедитесь, что он выполняется с достаточными правами (обычно это не проблема в хуках WooCommerce).
- Перезапись метаданных без условий. Это может привести к потере важных данных, нужно всегда проверять условия обновления.
Практические советы по производительности и безопасности
- Минимизируйте работу в обработчике. Не вызывайте тяжелые операции, например, внешние API, напрямую в хуке, лучше запускать их через WP-Cron или очереди.
- Проверяйте данные перед обновлением. Чтобы избежать лишних запросов, сравнивайте новое значение с существующим, обновляйте метаданные только при необходимости.
- Используйте
current_time()вместоdate(). Это учитывает часовой пояс WordPress. - Обрабатывайте ошибки. Например, проверяйте результат
update_post_meta()и логируйте ошибки при необходимости. - Безопасность почтовых уведомлений. Если отправляете почту, используйте валидные и защищённые методы, избегайте инъекций.
Сравнение вариантов реализации обновления метаданных
| Метод | Плюсы | Минусы | Компромисс |
|---|---|---|---|
Обновление в хуке woocommerce_order_status_changed | Мгновенное реагирование, простота реализации | Возможна нагрузка при частых изменениях, риск блокировки UI | Добавлять минимальный код, тяжелые задачи запускать отдельно |
| Использование WP-Cron для отложенной обработки | Снижает нагрузку, асинхронность | Задержка в выполнении, зависимость от cron | Комбинировать с хуком для постановки задач в очередь |
| Внешние сервисы через вебхуки | Масштабируемость, интеграция | Сложность настройки, задержки | Использовать для сложных интеграций, критичные метаданные обновлять локально |