Диагностика проблемы: почему нельзя изменить цену товара через стандартный интерфейс акций WooCommerce
Многие владельцы магазинов на WooCommerce сталкиваются с необходимостью массового изменения цен товаров во время акций, скидок или распродаж. Стандартный функционал WooCommerce позволяет задать скидку через поле «Цена по распродаже», однако это требует ручного ввода для каждого товара, что неудобно при большом каталоге.
Кроме того, при использовании динамических акций с разными условиями (категории, метки, даты) стандартные возможности не всегда позволяют гибко управлять ценами без установки дополнительных плагинов. Часто возникает задача автоматически применять скидку на определённые товары при выполнении условий акции.
Как автоматически менять цену товаров при акциях на WooCommerce без плагинов
Для решения задачи можно воспользоваться хуками WooCommerce и добавить кастомный код в файл functions.php вашей темы или в кастомный плагин. Основная идея — динамически изменять цену товара при выводе на фронтенде, не меняя базовую цену в базе.
Использование хука woocommerce_get_price для динамического изменения цены
Этот фильтр позволяет изменить цену товара на лету. Ниже пример кода, который снижает цену товаров категории "акции" на 20%:
add_filter('woocommerce_get_price', 'custom_discount_price', 10, 2);
function custom_discount_price($price, $product) {
if (is_admin()) return $price; // не менять в админке
if (has_term('aktsii', 'product_cat', $product->get_id())) { // категория 'акции'
$discount = 0.20; // 20% скидка
$new_price = $price * (1 - $discount);
return round($new_price, 2);
}
return $price;
}Расширение: учёт даты акции
Чтобы скидка применялась только в определённые даты, добавим проверку по текущей дате:
add_filter('woocommerce_get_price', 'custom_discount_price_date', 10, 2);
function custom_discount_price_date($price, $product) {
if (is_admin()) return $price;
$start_date = strtotime('2024-07-01');
$end_date = strtotime('2024-07-15');
$today = time();
if ($today >= $start_date && $today <= $end_date) {
if (has_term('aktsii', 'product_cat', $product->get_id())) {
$discount = 0.20;
$new_price = $price * (1 - $discount);
return round($new_price, 2);
}
}
return $price;
}Пошаговое руководство по применению кода
- Создайте дочернюю тему, если её ещё нет, чтобы не потерять изменения при обновлении.
- Откройте файл
functions.phpдочерней темы. - Вставьте один из приведённых выше фрагментов кода в конец файла.
- Убедитесь, что у товаров, на которые должна применяться скидка, есть категория с ярлыком
aktsii(сделайте это в админке WooCommerce). - Задайте даты акции в коде или удалите проверку по дате, если она не нужна.
- Сохраните изменения и загрузите файл на сервер, если редактировали локально.
Проверка результата после внедрения
Чтобы проверить, что цены изменились правильно:
- Перейдите на страницу товара, который относится к категории "акции".
- Убедитесь, что цена ниже на 20% (или на заданный процент).
- Проверьте, что в админке цена осталась без изменений.
- Отключите кэш, если он используется, чтобы увидеть изменения сразу.
- Проверьте работу на разных страницах: архивы, карточки товара, корзина.
Частые ошибки и как их исправить
- Ошибка: Цена не меняется на фронтенде.
Причина: Кэширование страниц или объектов.
Решение: Очистите кэш сайта и браузера, временно отключите кэш-плагины. - Ошибка: Цена меняется в админке.
Причина: Не было проверкиis_admin()в коде.
Решение: Добавьтеif (is_admin()) return $price;в начало функции. - Ошибка: Скидка применяется на все товары.
Причина: Неправильное условие проверки категории.
Решение: Проверьте, что ярлык категории указан правильно, используйте функциюhas_term()с правильными параметрами.
Практические советы по безопасности и производительности
- Не изменяйте цену в базе данных напрямую — используйте фильтры для динамического изменения.
- Добавляйте проверку
is_admin(), чтобы не влиять на административные операции. - Избегайте тяжелых запросов в хуках цены — используйте кэширование или предварительно задавайте метки и категории.
- При большом каталоге избегайте сложных условий, влияющих на скорость загрузки страниц.
- Для сложных условий и многократных акций рассмотрите возможность создания отдельного плагина с кешированием результатов.
Сравнение подходов: плагин vs код в functions.php
| Критерий | Решение через плагин | Решение через код | Компромисс |
|---|---|---|---|
| Гибкость | Высокая, готовые настройки | Максимальная, при кастомизации | Код требует навыков |
| Производительность | Может быть ниже из-за общего веса плагина | Выше при оптимальном коде | Риск ошибок при неправильном коде |
| Обновления | Обновляется разработчиком | Требует ручного сопровождения | Зависит от квалификации разработчика |
| Безопасность | Проверена сообществом | Зависит от качества кода | Требуется тестирование |
| Интеграция с другими функциями | Часто встроена | Нужно писать самому | Высокая кастомизация |