Диагностика проблемы: почему нужно менять цены автоматически при акциях
В WooCommerce часто возникает задача автоматически изменять цены товаров при проведении акций, не прибегая к громоздким плагинам. Например, вы хотите временно снизить цену на 20% или установить фиксированную скидочную цену на определённый период. Без автоматизации это приходится делать вручную: менять каждую цену, а потом возвращать обратно. Это неудобно и чревато ошибками.
Автоматическое изменение цен позволяет:
- Экономить время на массовых распродажах.
- Обеспечивать корректное отображение скидок на сайте и в корзине.
- Избежать ручных ошибок при выставлении цен.
Основные подходы к решению задачи в WooCommerce
В WooCommerce цены товаров хранятся в мета-полях _regular_price (обычная цена) и _sale_price (цена со скидкой). Чтобы автоматизировать изменение цен, можно программно устанавливать _sale_price для товаров в определённый период, а потом сбрасывать его.
Рассмотрим два варианта реализации:
1. Использование WP-Cron для автоматического запуска скрипта по расписанию
WP-Cron позволяет запускать PHP-функции по расписанию. Это удобно для установки и снятия акций в нужное время.
2. Изменение цен на лету при выводе товара без сохранения в базу
Этот метод подходит, если хотите показывать скидку, но не менять данные в БД (например, для временной акции или теста). Для этого используется фильтр 'woocommerce_get_price'.
Пошаговое решение с WP-Cron: установка и снятие акций по времени
Шаг 1. Добавляем функцию для запуска акции
function wpzoom_set_sale_price_for_products() {
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'post_status' => 'publish',
];
$products = get_posts($args);
foreach ( $products as $product_post ) {
$product = wc_get_product($product_post->ID);
$regular_price = (float) $product->get_regular_price();
if ( $regular_price > 0 ) {
$sale_price = $regular_price * 0.8; // скидка 20%
update_post_meta($product->get_id(), '_sale_price', $sale_price);
update_post_meta($product->get_id(), '_price', $sale_price);
}
}
}
Шаг 2. Добавляем функцию для снятия акции
function wpzoom_remove_sale_price_for_products() {
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'post_status' => 'publish',
];
$products = get_posts($args);
foreach ( $products as $product_post ) {
$product = wc_get_product($product_post->ID);
$regular_price = (float) $product->get_regular_price();
update_post_meta($product->get_id(), '_sale_price', '');
update_post_meta($product->get_id(), '_price', $regular_price);
}
}
Шаг 3. Добавляем расписание WP-Cron
function wpzoom_schedule_sale_events() {
if ( ! wp_next_scheduled( 'wpzoom_start_sale_event' ) ) {
// Запуск акции 1 декабря в 00:00
wp_schedule_event( strtotime('2024-12-01 00:00:00'), 'daily', 'wpzoom_start_sale_event' );
}
if ( ! wp_next_scheduled( 'wpzoom_end_sale_event' ) ) {
// Окончание акции 10 декабря в 23:59
wp_schedule_event( strtotime('2024-12-10 23:59:00'), 'daily', 'wpzoom_end_sale_event' );
}
}
add_action( 'wp', 'wpzoom_schedule_sale_events' );
add_action( 'wpzoom_start_sale_event', 'wpzoom_set_sale_price_for_products' );
add_action( 'wpzoom_end_sale_event', 'wpzoom_remove_sale_price_for_products' );
Шаг 4. Очистка при деактивации темы или плагина
function wpzoom_clear_sale_schedule() {
$timestamp_start = wp_next_scheduled('wpzoom_start_sale_event');
if ($timestamp_start) wp_unschedule_event($timestamp_start, 'wpzoom_start_sale_event');
$timestamp_end = wp_next_scheduled('wpzoom_end_sale_event');
if ($timestamp_end) wp_unschedule_event($timestamp_end, 'wpzoom_end_sale_event');
}
register_deactivation_hook( __FILE__, 'wpzoom_clear_sale_schedule' );
Проверка результата после внедрения
Чтобы убедиться, что автоматическое изменение цен работает корректно:
- Проверьте в админке WooCommerce, что у товаров появляется
sale priceв указанный период. - Перейдите на страницу товара на сайте — должна отображаться сниженная цена.
- В корзине и на странице оформления заказа скидка должна сохраняться.
- Проверьте логи WP-Cron, убедитесь, что события запускаются в нужное время.
Частые ошибки и как их исправить
- WP-Cron не срабатывает: Проверьте, что на сайте есть трафик, либо настройте системный cron в сервере для запуска
wp-cron.php. - Цена не обновляется после запуска функции: Проверьте, что у товаров есть заполнено поле
_regular_price. Без него скидка не посчитается. - Скидка не отображается на фронтенде: Проверьте, не кешируется ли страница. Очистите кеш, отключите плагины кеширования для теста.
- Расписание создаётся многократно: Используйте
wp_next_scheduledдля проверки перед созданием событий.
Практические советы по безопасности и производительности
- При массовом обновлении цен используйте WP-CLI для ускорения и снижения нагрузки:
wp post list --post_type=product --field=ID | xargs -n1 -P10 -I % wp post meta update % _sale_price 80с нужным значением. - Для больших магазинов разбивайте обновление цен на части — например, обновляйте по 100 товаров за один запуск WP-Cron.
- Не оставляйте в базе неиспользуемые мета-поля — удаляйте
_sale_priceпосле окончания акции. - Резервируйте базу перед массовыми изменениями цен.
Сравнение подходов: WP-Cron vs изменение цен на лету
| Критерий | WP-Cron (сохранение в БД) | Изменение цен на лету (фильтр) |
|---|---|---|
| Влияние на базу данных | Меняет цены в базе | Не меняет, только отображение |
| Производительность | Нагрузка при массовом обновлении | Нагрузка при каждом выводе цены |
| Сложность реализации | Средняя | Низкая |
| Возможность массовых акций | Отлично подходит | Только для временных визуальных скидок |
| Совместимость с корзиной и оплатой | Полная | Может требовать дополнительной настройки |
Пример использования фильтра для временной скидки без записи в базу
add_filter('woocommerce_get_price', 'wpzoom_temporary_price_discount', 10, 2);
function wpzoom_temporary_price_discount($price, $product) {
$current_time = current_time('timestamp');
$start = strtotime('2024-12-01 00:00:00');
$end = strtotime('2024-12-10 23:59:59');
if ( $current_time >= $start && $current_time <= $end ) {
return $price * 0.8; // скидка 20%
}
return $price;
}