Проблема: необходимость массового изменения цен в WooCommerce по заданным условиям
В интернет-магазинах на WooCommerce часто возникает задача автоматически менять цены товаров на основе определённых условий: распродажа, скидка для определённой категории, изменение цены при достижении определённого объёма продаж и т. п. Ручное редактирование при большом каталоге неудобно и трудозатратно.
Диагностика задачи: как определить, что нужно автоматизировать
Прежде чем внедрять код, определите чёткие условия изменения цены:
- Какие товары попадают под изменение (по категории, тегу, атрибуту или метаданным)?
- Какое именно изменение цены нужно — фиксированная скидка, процент, новая цена?
- Когда должна происходить автоматизация — при загрузке страницы, в cron-задаче, при сохранении товара?
Пошаговое решение: пример автоматического снижения цен на 10% для товаров категории «Скидки»
1. Добавляем фильтр для изменения цены на фронтенде
Для изменения отображаемой цены без изменения в базе используем фильтр woocommerce_get_price и woocommerce_get_sale_price. Пример кода в functions.php дочерней темы или плагине:
add_filter('woocommerce_get_price', 'custom_discount_category_price', 10, 2);
add_filter('woocommerce_get_sale_price', 'custom_discount_category_price', 10, 2);
function custom_discount_category_price($price, $product) {
if (!$product instanceof WC_Product) {
return $price;
}
if (has_term('skidki', 'product_cat', $product->get_id())) {
$discount = 0.10; // 10% скидка
$price = $price * (1 - $discount);
}
return $price;
}2. Автоматическое обновление цен в базе по расписанию (cron)
Если нужно обновлять реальную цену товаров, лучше сделать cron-задачу. Пример функции, которая снижает цены в базе на 10% для категории «Скидки»:
function update_prices_for_discount_category() {
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => [
[
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'skidki'
]
],
'fields' => 'ids'
];
$products = get_posts($args);
foreach ($products as $product_id) {
$product = wc_get_product($product_id);
if (!$product) continue;
$regular_price = $product->get_regular_price();
if (!$regular_price) continue;
$new_price = $regular_price * 0.90; // минус 10%
$product->set_price($new_price);
$product->save();
}
}
// Регистрируем wp-cron событие (делать один раз)
if (!wp_next_scheduled('update_discounted_prices_daily')) {
wp_schedule_event(time(), 'daily', 'update_discounted_prices_daily');
}
add_action('update_discounted_prices_daily', 'update_prices_for_discount_category');Этот код ежедневно снижает цены товаров из категории «skidki» на 10%. Не забудьте заменить slug категории на ваш.
Проверка результата после внедрения
- Для фильтра цены — откройте страницу товара из категории «skidki» и убедитесь, что цена на витрине уменьшена на 10%.
- Для cron-задачи — в базе данных (wp_postmeta) проверьте, что у продуктов изменилось значение
_priceи_regular_price. Можно использовать запрос в phpMyAdmin:SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (…список ID товаров...) AND meta_key IN ('_price', '_regular_price'); - Проверьте в админке WooCommerce, что цена товара изменилась.
Частые ошибки и как их исправить
- Фильтр не срабатывает на странице корзины или в виджетах: WooCommerce может кешировать цены, используйте фильтры
woocommerce_product_get_priceиwoocommerce_product_get_sale_priceвместоwoocommerce_get_price. - Cron-задача не запускается: Убедитесь, что WP-Cron включён и работает. Для теста запустите
wp cron event run --due-nowиз командной строки (WP-CLI). - Изменение цены ломает логику скидок или купонов: Тестируйте изменения на тестовом сайте, учитывайте кэш и совместимость с плагинами скидок.
Практические советы по безопасности и производительности
- Не меняйте цены массово на продакшене без бэкапа базы. Используйте staging-среду.
- Для больших каталогов используйте WP-CLI или пакетные обновления, чтобы избежать таймаутов.
- Кеширование: Если используете кеширующие плагины, очищайте кеш после изменения цен.
- Безопасность: Не давайте необоснованный доступ к функциям изменения цен через фронтенд или публичные AJAX-запросы.
Сравнение подходов: фильтр vs обновление в базе
| Критерий | Фильтр изменения цены | Обновление цены в базе |
|---|---|---|
| Влияние на данные | Отображение, цена в базе не меняется | Цена меняется в базе, влияет на все операции |
| Обратимость | Легко отменить, убрав фильтр | Нужен бэкап или дополнительный код для возврата |
| Производительность | Незначительная нагрузка, работает на лету | Нагрузка при массовом обновлении, нужен cron |
| Совместимость с плагинами | Может конфликтовать с плагинами скидок | Совместим, т.к. меняет реальные цены |