Диагностика задачи: когда нужно менять стоимость товара в корзине
В WooCommerce иногда требуется динамически изменить цену товара на этапе корзины: например, для предоставления скидок по определённым условиям, добавления наценок или корректировки стоимости в зависимости от пользовательских данных. Прямая правка цены товара в базе не подходит — нужно использовать хуки WooCommerce, чтобы изменения были временными и корректно отображались в интерфейсе и заказе.
Основные хуки для изменения стоимости товара в корзине
В WooCommerce для модификации цены товара в корзине используются фильтры на уровне объекта WC_Cart_Item и корзины в целом. Основные хуки:
woocommerce_before_calculate_totals— самый популярный хук для изменения цены в корзине перед пересчётом итогов.woocommerce_cart_item_price— для изменения отображаемой цены товара в корзине и на страницах.woocommerce_get_price_html— для изменения цены в витрине, если нужно.
Пример: скидка 10% на все товары в корзине
add_action('woocommerce_before_calculate_totals', 'apply_10_percent_discount', 10, 1);
function apply_10_percent_discount($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
foreach ($cart->get_cart() as $cart_item) {
$original_price = $cart_item['data']->get_price();
$discounted_price = $original_price * 0.9; // 10% скидка
$cart_item['data']->set_price($discounted_price);
}
}Пошаговое решение: динамическое изменение цены по условию
Допустим, нужно добавить наценку 100 рублей на товары определённой категории (ID категории 15) в корзине.
Шаг 1 — подключаем хук woocommerce_before_calculate_totals
Этот хук вызывается перед подсчётом итогов корзины и позволяет изменить цену товара в объекте WC_Product.
Шаг 2 — проверяем категорию товара и изменяем цену
add_action('woocommerce_before_calculate_totals', 'add_surcharge_for_category_15', 20, 1);
function add_surcharge_for_category_15($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
if (has_term(15, 'product_cat', $product->get_id())) {
$original_price = $product->get_price();
$new_price = $original_price + 100;
$product->set_price($new_price);
}
}
}Шаг 3 — проверяем изменение цены в фронтенде
Обновите страницу корзины и убедитесь, что у товаров из категории с ID 15 цена увеличилась на 100 рублей. Для проверки можно включить отладку и вывести текущие цены в консоль или добавить временный error_log в функцию.
Проверка результата после внедрения
- Откройте страницу корзины в режиме инкогнито или после очистки кеша.
- Добавьте в корзину товар из нужной категории и другой товар.
- Проверьте, что цена товара из категории 15 увеличена на 100 рублей, а остальные без изменений.
- Проверьте итоговую сумму корзины.
- Создайте тестовый заказ и убедитесь, что цена сохраняется в заказе.
Частые ошибки и как их исправить
- Изменения не отображаются: возможно, кеш страницы или кэш объектов WooCommerce блокирует обновление. Очистите кеш сайта и браузера.
- Цена меняется в админке: добавьте проверку
if (is_admin() && !defined('DOING_AJAX')) return;чтобы не менять цену в админке. - Цена сбрасывается после обновления страницы: убедитесь, что изменение цены происходит на каждом вызове
woocommerce_before_calculate_totals. - Цена изменяется некорректно для нескольких товаров: проверьте работу цикла и логику условий, особенно если работаете с вариативными товарами.
Практические советы по безопасности и производительности
- Не храните изменённые цены в пользовательских метаданных — это может привести к рассинхронизации.
- Избегайте тяжёлых запросов и сложных вычислений внутри хука, чтобы не замедлять загрузку корзины.
- Используйте проверку
is_admin()иDOING_AJAXдля ограничения области действия кода. - Тестируйте изменения с разными плагинами кеширования и режимами работы сайта.
- При необходимости кешируйте результаты сложных условий вне цикла, чтобы уменьшить нагрузку.
Сравнение способов изменения цены товара в корзине
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
Хук woocommerce_before_calculate_totals |
Динамическое изменение цены, сохраняется в заказе | Нужно правильно обрабатывать условия, возможны проблемы с кешем | Для всех случаев изменения цены в корзине |
Фильтр woocommerce_cart_item_price |
Изменяет только отображение цены | Цена в заказе не меняется | Когда нужно только визуально показать скидку, без изменения итогов |
| Изменение цены через пользовательские метаданные | Можно сохранять сложные правила | Сложнее поддерживать, возможны ошибки при сохранении заказа | Редкие случаи, когда нужно хранить цену отдельно |