Проблема: необходимость автоматической реакции на смену статуса заказа в WooCommerce
В стандартном WooCommerce нет встроенного механизма для автоматического выполнения кастомных действий при изменении статуса заказа. Часто разработчикам и владельцам магазинов нужно не просто видеть смену статуса заказа, а автоматически запускать дополнительные процессы: отправку уведомлений, обновление внешних систем, запись в логи и т.п.
Диагностика проблемы: как понять, что статус заказа меняется, но кастомные действия не выполняются
Если ваш код, привязанный к смене статуса заказа, не срабатывает, убедитесь в следующем:
- Вы используете правильные хуки WooCommerce.
- Ваш код подключен в нужном месте (functions.php темы или плагина).
- Нет конфликтов с другими плагинами или темой.
- Вы проверяете изменения статуса именно для нужных статусов.
Для диагностики можно добавить простой лог в файл wp-content/debug.log:
add_action( 'woocommerce_order_status_changed', 'log_order_status_change', 10, 4 );
function log_order_status_change( $order_id, $old_status, $new_status, $order ) {
if ( defined('WP_DEBUG') && WP_DEBUG ) {
error_log("Order #$order_id status changed from $old_status to $new_status");
}
}
Если в логе появляется запись при смене статуса — ваш хук работает.
Пошаговое решение: настройка автоматического отслеживания изменений статуса заказа
1. Использование хука woocommerce_order_status_changed
Этот хук запускается при любом изменении статуса заказа. Он принимает 4 параметра:
$order_id— ID заказа;$old_status— старый статус;$new_status— новый статус;$order— объект WC_Order.
Пример кода для выполнения кастомного действия при смене на статус completed:
add_action( 'woocommerce_order_status_changed', 'custom_on_order_completed', 10, 4 );
function custom_on_order_completed( $order_id, $old_status, $new_status, $order ) {
if ( 'completed' === $new_status ) {
// Выполнить нужные действия, например, отправить письмо
$to = $order->get_billing_email();
$subject = 'Ваш заказ выполнен';
$message = 'Спасибо за покупку! Ваш заказ #' . $order_id . ' выполнен.';
wp_mail( $to, $subject, $message );
}
}
2. Подписка на смену конкретных статусов
Можно использовать хуки вида woocommerce_order_status_{new_status} для обработки определенных статусов. Например:
add_action( 'woocommerce_order_status_processing', 'handle_order_processing' );
function handle_order_processing( $order_id ) {
$order = wc_get_order( $order_id );
// кастомные действия
}
Проверка результата после внедрения
Чтобы проверить, что отслеживание работает:
- Включите WP_DEBUG и WP_DEBUG_LOG в
wp-config.php:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
- Измените статус заказа вручную в админке WooCommerce.
- Проверьте файл
wp-content/debug.logна наличие записей от вашего кода. - Убедитесь, что кастомные действия (например, отправка письма) выполнились.
Частые ошибки и как их исправить
- Хук не срабатывает: убедитесь, что код подключен в functions.php активной темы или в плагине.
- Ошибки из-за отсутствия объекта заказа: всегда проверяйте, что
$orderполучен корректно, используйтеwc_get_order(), если нужно. - Отправка писем не работает: проверьте настройки почты на сервере, используйте SMTP-плагин для корректной отправки.
- Код срабатывает не для всех статусов: убедитесь, что используете правильные названия статусов (без префикса
wc-).
Практические советы по безопасности и производительности
- Не выполняйте тяжелые операции в хук синхронно — если нужно, используйте отложенное выполнение через WP-Cron или внешние очереди.
- Проверяйте права пользователя, если в вашем коде есть изменение данных.
- Используйте nonce и валидацию, если пользовательские данные передаются в обработчики.
- Для логирования используйте условие
WP_DEBUG, чтобы не засорять логи на продакшене.
Сравнение вариантов реализации отслеживания изменений статуса
| Метод | Преимущества | Недостатки |
|---|---|---|
woocommerce_order_status_changed | Универсальный, срабатывает на все изменения статуса Доступ к старому и новому статусу, объекту заказа | Обработка всех статусов требует условий в коде |
woocommerce_order_status_{status} | Простой код для конкретного статуса Чистый и понятный | Нужно писать свой хук для каждого статуса |