Диагностика задачи: зачем менять цену товара программно
В WooCommerce часто возникает необходимость динамически изменять цену товара в зависимости от условий: количество в корзине, роль пользователя, дата или акции. Стандартных средств для гибких правил ценообразования мало, а сторонние плагины часто слишком громоздки или платные.
Чаще всего пользователи спрашивают: как автоматически снижать цену товара, если в корзине больше N штук; как менять цену для определённых ролей; как добавить скидку в зависимости от даты или категории товара.
Пошаговое решение: изменение цены через хук woocommerce_before_calculate_totals
Для динамического изменения цены в WooCommerce лучше всего использовать хук woocommerce_before_calculate_totals. Он позволяет менять цену товара перед расчётом итогов корзины и заказа.
Пример: уменьшим цену товара на 10% если в корзине больше 3 штук:
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_adjustment', 20, 1);
function custom_dynamic_price_adjustment( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
foreach ( $cart->get_cart() as $cart_item ) {
$quantity = $cart_item['quantity'];
$product = $cart_item['data'];
$original_price = $product->get_regular_price();
if ( $quantity > 3 ) {
$discounted_price = $original_price * 0.9; // скидка 10%
$product->set_price( $discounted_price );
} else {
$product->set_price( $original_price );
}
}
}Изменение цены для пользователей с ролью "оптовик"
Для изменения цены в зависимости от роли пользователя добавим проверку роли:
add_action('woocommerce_before_calculate_totals', 'role_based_price_adjustment', 20, 1);
function role_based_price_adjustment( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
if ( current_user_can('wholesale_customer') ) { // замените на вашу роль
foreach ( $cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
$original_price = $product->get_regular_price();
$discounted_price = $original_price * 0.8; // скидка 20%
$product->set_price( $discounted_price );
}
}
}Проверка результата
Чтобы проверить, что цена изменяется корректно:
- Добавьте товар в корзину больше 3 штук и убедитесь, что стоимость изменилась на 10%.
- Авторизуйтесь под пользователем с ролью
wholesale_customerи проверьте скидку 20% на все товары. - Обновите страницу корзины, чтобы увидеть актуальную цену.
- Для отладки можно временно добавить
error_log('Цена изменена для товара ID: ' . $product->get_id());внутри цикла.
Частые ошибки и как исправить
- Цена не меняется: проверьте, не кэшируется ли корзина или страница. Очистите кеш, отключите плагины кеширования.
- Цены сбрасываются после обновления страницы: убедитесь, что в коде не вызывается несколько раз
set_priceи нет конфликтов с другими плагинами. - Изменения влияют на все заказы: код должен работать только в корзине и на этапе оформления, а не менять цену товара глобально.
- Ошибка PHP или белый экран: проверьте синтаксис, используйте
error_logи включите WP_DEBUG для диагностики.
Практические советы по безопасности и производительности
- Не меняйте цены на уровне базы данных — только во время расчёта в корзине.
- Добавляйте проверки
is_admin()иDOING_AJAX, чтобы не влиять на админку и AJAX запросы без необходимости. - Кэшируйте результаты вычислений, если скидки сложные, чтобы не нагружать сервер.
- Для массовых изменений цен лучше использовать специализированные плагины, если логика становится слишком сложной.
Сравнение подходов: код vs плагины
| Критерий | Ручной код | Плагин (например, WooCommerce Dynamic Pricing) | Компромисс |
|---|---|---|---|
| Гибкость | Высокая для разработчиков | Удобный интерфейс, много настроек | Код требует знаний, плагины могут быть избыточны |
| Производительность | Оптимизирован под задачу | Может замедлять сайт | Код лучше в производительности |
| Обновления и поддержка | Зависит от разработчика | Регулярные обновления | Плагины проще для непрофи |
| Стоимость | Бесплатно, но нужно время | Часто платные | Код экономит деньги |