В чем проблема: необходимость менять цены товаров в WooCommerce по расписанию
В интернет-магазинах часто требуется менять цены на товары в определенные дни или часы — например, для акций, распродаж, праздничных скидок. В WooCommerce нет встроенного инструмента для автоматического управления ценами по расписанию. Вручную менять цены неудобно и чревато ошибками, особенно при большом каталоге.
Диагностика задачи и требования
- Автоматическое повышение или понижение цены товаров в заданное время.
- Возможность задать расписание для изменений — по дате и времени.
- Поддержка как всех товаров, так и отдельных категорий или тегов.
- Возврат к исходной цене после окончания периода акции.
- Минимальное влияние на производительность сайта.
Пошаговое решение: как реализовать автоматическую смену цен по расписанию
1. Создаем пользовательское поле для хранения базовой цены
Чтобы не перезаписывать основную цену навсегда, лучше сохранить исходную цену в отдельном метаполе _base_price. Это позволит откатывать цену после окончания акции.
function save_base_price_on_product_save( $post_id ) {
if ( get_post_type( $post_id ) !== 'product' ) {
return;
}
$product = wc_get_product( $post_id );
if ( ! $product ) {
return;
}
$base_price = get_post_meta( $post_id, '_base_price', true );
$regular_price = $product->get_regular_price();
if ( empty( $base_price ) ) {
update_post_meta( $post_id, '_base_price', $regular_price );
}
}
add_action( 'save_post', 'save_base_price_on_product_save' );2. Создаем функцию, которая меняет цены товаров по расписанию
Далее пишем функцию, которая будет запускаться через WP-Cron и менять цену по заданному условию.
function apply_scheduled_price_changes() {
// Пример расписания: с 1 по 7 число каждого месяца - скидка 20%
$now = current_time( 'timestamp' );
$day = (int) date( 'j', $now );
// Получаем все товары, для упрощения - все опубликованные
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => -1,
);
$products = get_posts( $args );
foreach ( $products as $post ) {
$product = wc_get_product( $post->ID );
$base_price = get_post_meta( $post->ID, '_base_price', true );
if ( ! $base_price ) {
$base_price = $product->get_regular_price();
update_post_meta( $post->ID, '_base_price', $base_price );
}
if ( $day >= 1 && $day <= 7 ) {
// Акция: скидка 20%
$new_price = $base_price * 0.8;
$product->set_price( $new_price );
$product->set_regular_price( $new_price );
$product->save();
} else {
// Возвращаем базовую цену
if ( $product->get_regular_price() != $base_price ) {
$product->set_price( $base_price );
$product->set_regular_price( $base_price );
$product->save();
}
}
}
}3. Добавляем задачу в WP-Cron для ежедневного запуска
Теперь нужно настроить запуск этой функции раз в сутки, например, в 00:01.
function schedule_price_change_cron() {
if ( ! wp_next_scheduled( 'daily_price_change_event' ) ) {
wp_schedule_event( strtotime( '00:01:00' ), 'daily', 'daily_price_change_event' );
}
}
add_action( 'wp', 'schedule_price_change_cron' );
add_action( 'daily_price_change_event', 'apply_scheduled_price_changes' );Проверка результата после внедрения
- Проверьте наличие метаполя
_base_priceу товаров через phpMyAdmin или плагин для работы с метаполями (например, Advanced Custom Fields). - Запустите функцию вручную в режиме отладки, вызвав
apply_scheduled_price_changes()через консоль WP-CLI или временно через admin-ajax. - Проверьте цену товаров в периоды действия акции и вне их — должна изменяться согласно расписанию.
- Проверьте логи ошибок PHP для отсутствия предупреждений.
Частые ошибки и как их исправить
- Цены не меняются: возможно, WP-Cron не запущен на сервере. Проверьте, работает ли системный cron или используйте плагин WP Crontrol для диагностики.
- Не сохраняется базовая цена: убедитесь, что функция
save_base_price_on_product_saveдобавлена и срабатывает при сохранении товара. - Изменения цены не отображаются на фронтенде: очистите кэш сайта и браузера, проверьте, не переопределяют ли цены другие плагины для кэширования или оптимизации.
- Производительность падает при большом количестве товаров: для больших магазинов замените выборку
get_postsна WP_Query с пагинацией или используйте batch-обработку.
Практические советы для безопасности и производительности
- Не используйте постоянные прямые обновления цен на все товары в одном запросе — разбивайте на партии по 50–100 товаров, чтобы избежать таймаутов.
- Сохраняйте базовую цену только один раз, при первом сохранении товара, чтобы не перезаписывать её случайно.
- Логируйте изменения цен в отдельную таблицу или файл для аудита, особенно если цены меняются часто.
- Отключайте WP-Cron и настраивайте системный cron для надежного выполнения задач на сервере.
- Для сложных условий акций используйте собственные метаполя или сторонние плагины для управления распродажами (например, WooCommerce Dynamic Pricing & Discounts), но имейте в виду, что кастомный код гибче и не нагружает базу лишними запросами.
Сравнение вариантов реализации автоматического изменения цен
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| Плагин динамических цен | Использование готовых плагинов для акций и скидок с расписанием | Быстрая настройка, готовый UI, поддержка сложных условий | Нагрузка на сайт, цена плагина, ограниченная кастомизация |
| Кастомный код с WP-Cron | Реализация через функции и планировщик WP-Cron | Полный контроль, минимальная нагрузка, нет сторонних зависимостей | Требует навыков разработки, нужно следить за cron |
| Ручное изменение цен | Ручное редактирование цен в админке | Простота, никаких технических знаний | Риск ошибок, невозможно масштабировать |