Диагностика проблемы: почему стандартные распродажи WooCommerce пересчитывают атрибуты
При стандартном использовании ценовых акций в WooCommerce (через поле "Старая цена" и "Цена со скидкой") система пересчитывает все связанные атрибуты товаров, что иногда приводит к нежелательным эффектам — например, изменению цен вариаций или потере кастомных настроек. Это особенно критично, если у товара сложные вариации с разными ценами и атрибутами.
Проверить это можно так:
- Создайте товар с вариациями, у каждой вариации установите уникальную цену.
- Включите скидку на товар (прямо на уровне товара или через акции).
- Проверьте, изменились ли цены вариаций после применения скидки.
Если цены вариаций меняются, значит, стандартный механизм не подходит для ваших задач.
Пошаговое решение: как автоматически менять цену товара при распродаже без затрагивания атрибутов
1. Использование фильтра woocommerce_product_get_price
Для изменения цены на лету, без изменения данных в базе, можно использовать фильтр woocommerce_product_get_price, который применяется при получении цены товара. Это позволяет динамически изменять цену только на фронтенде, не трогая атрибуты и вариации.
2. Пример кода для автоматического уменьшения цены на 20%
add_filter('woocommerce_product_get_price', 'custom_discount_price', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'custom_discount_price', 10, 2);
function custom_discount_price($price, $product) {
// Проверка, что это не админка и цена задана
if (is_admin() || empty($price)) {
return $price;
}
// Логика применения скидки: например, только для товаров из категории "sale"
if (has_term('sale', 'product_cat', $product->get_id())) {
// Уменьшаем цену на 20%
$new_price = $price * 0.8;
// Возвращаем новую цену с округлением до 2 знаков
return round($new_price, 2);
}
return $price;
}3. Как применить скидку только на отдельные товары или категории
В примере выше мы проверяем категорию товара через has_term. Можно изменить условие на любой кастомный критерий, например, мета-поле или тег.
Проверка результата после внедрения
- Очистите кэш сайта и браузера.
- Откройте страницу товара с вариациями, которые должны попасть под скидку.
- Проверьте цены вариаций — они должны отображаться со скидкой, но в базе цены не изменились.
- В админке цены товара и вариаций остаются без изменений.
- Сделайте заказ, чтобы проверить, что в корзине и на чеке цена применяется корректно.
Частые ошибки и как их исправить
- Скидка не отображается — проверьте, что фильтр подключён и условие для скидки выполняется (например, категория задана верно).
- Цена меняется и в админке — возможно, код вставлен в шаблон функции, вызывающий сохранение цены. Важно, чтобы изменение было только на этапе получения цены, а не сохранения.
- Вариации показывают разные цены, но корзина считает по старой — проверьте, что фильтры применяются к обоим хукам:
woocommerce_product_get_priceиwoocommerce_product_get_regular_price. - Конфликты с кэшированием — при наличии плагинов кэширования очистите кэш и проверьте, не кэшируются ли цены на стороне сервера.
Практические советы по производительности и безопасности
- Не используйте в коде тяжелые запросы к базе внутри фильтров. Все логические проверки должны быть максимально простыми.
- При большом каталоге для проверки категорий используйте кеширование результатов
has_termили меток. - Избегайте прямой записи цены в базу — изменяйте цену только на этапе отображения, чтобы не сломать логику WooCommerce.
Сравнение методов изменения цены при распродажах
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| Стандартные поля "Старая цена" и "Цена" | Редактирование цены в админке | Простота Поддерживается WooCommerce | Пересчет атрибутов Изменение цены в базе |
Фильтр woocommerce_product_get_price | Динамическое изменение цены на фронтенде | Не трогает базу Гибкость логики скидок | Необходим кастомный код Возможны конфликты с плагинами |
| Плагины скидок и акций | Готовые решения для управления скидками | Простота настройки Много функций | Могут менять цены в базе Зависимость от стороннего кода |