Диагностика задачи: зачем менять стоимость товара программно
В WooCommerce стандартно цены задаются вручную или через массовое редактирование. Но иногда бизнес-логика требует менять цену товара динамически — например, при заказе определённого количества, по времени, для пользователей с определённой ролью или при наличии других товаров в корзине. Сделать это вручную неудобно и неэффективно, а плагинов с гибкой кастомизацией часто не хватает.
Цель статьи — показать, как автоматически изменять цену товара программно с помощью хуков WooCommerce, чтобы подстроиться под любые бизнес-условия.
Основные хуки для изменения цены товара в WooCommerce
Для изменения стоимости товара перед отображением и добавлением в корзину используются фильтры:
woocommerce_product_get_price— для изменения основной цены товара.woocommerce_product_get_regular_price— для изменения базовой цены (без скидок).woocommerce_before_calculate_totals— для изменения цены уже в объекте товара в корзине.
Обычно для динамической цены в корзине используют woocommerce_before_calculate_totals, ведь изменение цены на уровне объекта товара отражается во всех расчетах.
Пошаговое решение: изменение цены товара при заказе от 5 штук
Шаг 1. Добавляем фильтр для изменения цены в корзине
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_bulk_discount', 20, 1);
function custom_dynamic_price_bulk_discount($cart) {
if (is_admin() && !defined('DOING_AJAX')) return; // не менять в админке
foreach ($cart->get_cart() as $cart_item) {
$quantity = $cart_item['quantity'];
$product = $cart_item['data'];
$regular_price = floatval($product->get_regular_price());
if ($quantity >= 5) { // скидка 10% при покупке 5 и более
$new_price = $regular_price * 0.9;
$product->set_price($new_price);
} else {
$product->set_price($regular_price); // сброс цены
}
}
}В этом коде мы перебираем товары в корзине и при количестве 5+ меняем цену на 90% от базовой.
Шаг 2. Тестируем изменение цены на фронтенде
- Добавьте в корзину товар с количеством от 1 до 4 — цена останется без изменений.
- Добавьте количество 5 или больше — цена должна автоматически уменьшиться на 10%.
Проверка результата: как убедиться, что цена изменилась
Чтобы проверить, что динамическое изменение цены работает:
- Добавьте товар в корзину на разное количество и обратите внимание на цену в корзине и на странице оформления заказа.
- Проверьте, что итоговая сумма заказа учитывает скидку.
- Включите отладку WooCommerce (константа
WP_DEBUG) и проверьте, что нет ошибок.
Частые ошибки и как их исправить
- Цена не меняется в корзине
Проверьте, что хук добавлен с правильным приоритетом и что объект товара — это классWC_Product. Иногда нужно использовать$cart_item['data']->set_price(), а не менять цену напрямую. - Цена меняется и в админке
Добавьте проверкуif (is_admin() && !defined('DOING_AJAX')) return;, чтобы изменения не влияли на админ-панель. - Изменения не применяются к вариативным товарам
Для вариативных товаров нужно учитывать цену вариаций, а не родительского товара.
Практические советы по безопасности и производительности
- Не храните изменённые цены в базе данных — меняйте цену только динамически с помощью фильтров.
- Добавляйте проверки, чтобы не влиять на админку и ajax-запросы, это снижает риск ошибок.
- Для сложных условий лучше вынести логику в отдельные методы, чтобы код был читабельным и поддерживаемым.
Пример: изменение цены для пользователей с ролью "оптовик"
add_action('woocommerce_before_calculate_totals', 'custom_price_for_wholesaler', 20, 1);
function custom_price_for_wholesaler($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
$user = wp_get_current_user();
if (in_array('wholesaler', (array) $user->roles)) {
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$regular_price = floatval($product->get_regular_price());
$discounted_price = $regular_price * 0.85; // скидка 15%
$product->set_price($discounted_price);
}
}
}Сравнение вариантов реализации изменения цены
| Метод | Преимущества | Недостатки |
|---|---|---|
Фильтр woocommerce_before_calculate_totals | Динамическое изменение в корзине, учитывается в финальных расчетах | Не влияет на цену на странице магазина без дополнительного кода |
Фильтры woocommerce_product_get_price | Меняет цену для отображения на страницах магазина | Не меняет цену в корзине автоматически, требуется дополнительный код |
| Плагины скидок | Готовые решения без кода, множество настроек | Может быть избыточно, не всегда гибко под уникальные условия |