Диагностика задачи: зачем менять цены товаров автоматически
В WooCommerce часто возникает задача временно менять цены товаров — скидки на выходные, акции в определённые даты, динамическое ценообразование по расписанию. Ручное обновление цен при большом количестве товаров неудобно и подвержено ошибкам. Поэтому практичные разработчики автоматизируют этот процесс с помощью хуков и WP-Cron.
Выбор подхода: хуки WooCommerce и WP-Cron
Для изменения цены в WooCommerce нужно использовать фильтр woocommerce_product_get_price или woocommerce_get_price_html. Для запуска задачи по расписанию — WP-Cron. Варианты:
| Способ | Плюсы | Минусы |
|---|---|---|
| Фильтр изменения цены + WP-Cron для смены статуса/мета | Гибкость, цены меняются динамично без обновления базы | Сложнее поддерживать, нужно правильно планировать WP-Cron |
| Менять цену напрямую в мета полях через WP-Cron | Простота реализации, меньше нагрузки на фильтры | Возможны конфликты с кэшированием, нужно сбрасывать кэш |
| Использование плагинов для динамического ценообразования | Быстро, без кода | Стоимость, зависимость от сторонних решений |
Пошаговое решение: автоматическое изменение цены с WP-Cron и хуком
1. Добавляем WP-Cron задачу для изменения цен
В functions.php или в вашем плагине регистрируем событие, которое будет запускаться, например, ежедневно:
add_action('init', function() {
if (!wp_next_scheduled('custom_update_product_prices')) {
wp_schedule_event(time(), 'daily', 'custom_update_product_prices');
}
});2. Реализуем обработчик обновления цен
В обработчике можно менять мета-данные товаров, например, добавлять мета с временной скидкой:
add_action('custom_update_product_prices', function() {
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'fields' => 'ids',
];
$products = get_posts($args);
foreach ($products as $product_id) {
$product = wc_get_product($product_id);
// Пример логики: в выходные дни устанавливаем скидку 20%
$weekday = date('N'); // 6-суббота, 7-воскресенье
if (in_array($weekday, [6,7])) {
$regular_price = $product->get_regular_price();
$sale_price = $regular_price * 0.8;
update_post_meta($product_id, '_sale_price', $sale_price);
update_post_meta($product_id, '_price', $sale_price);
} else {
// Убираем скидку в будни
delete_post_meta($product_id, '_sale_price');
update_post_meta($product_id, '_price', $product->get_regular_price());
}
}
});3. Фильтруем цену товара для корректного отображения
Чтобы WooCommerce использовал корректную цену, добавим фильтр:
add_filter('woocommerce_product_get_price', function($price, $product) {
$sale_price = get_post_meta($product->get_id(), '_sale_price', true);
if (!empty($sale_price)) {
return $sale_price;
}
return $price;
}, 10, 2);Как проверить, что решение работает
- Проверить расписание WP-Cron в админке или с помощью плагина WP Crontrol — должно быть событие
custom_update_product_prices, запускающееся ежедневно - В выходные открыть страницу товара — цена должна быть со скидкой 20%
- В будни цена должна вернуться к обычной
- Включить режим отладки WooCommerce (WC_DEBUG) и проверить, что цена корректно подтягивается из мета
Частые ошибки при автоматическом изменении цены и их исправление
- WP-Cron не срабатывает: Убедитесь, что на сайте есть посещения, которые запускают WP-Cron. Для теста используйте плагин WP Crontrol для ручного запуска задач.
- Цена не обновляется на фронтенде: Проверьте, что фильтр
woocommerce_product_get_priceкорректно реализован и вызывается. - Кэширование мешает увидеть изменения: Очистите кэш сайта и браузера. Если используется объектный кэш, сбросьте его.
- Цена не откатывается в будние дни: Проверьте логику условия в обработчике WP-Cron и корректность удаления мета полей.
Практические советы по безопасности и производительности
- Для большого каталога товаров лучше разбивать обновление на части, чтобы избежать таймаутов и превышения лимитов памяти. Например, обрабатывать по 50 товаров за один запуск WP-Cron.
- Добавьте проверку nonce или capability, если планируете запускать обновление из интерфейса админки.
- Используйте транзиенты для кеширования результата вычислений, чтобы не нагружать сайт лишними запросами.
- Для критичных сайтов рассмотрите внешние cron-сервисы вместо WP-Cron, чтобы задачи запускались стабильно.