Проблема: некорректное отображение цены вариативного товара при выборе опций
В WooCommerce часто возникает задача динамически корректировать стоимость вариативного товара при выборе разных опций (атрибутов). По умолчанию WooCommerce отображает цену варианта, но иногда требуется применять дополнительные наценки или скидки на основе выбранных атрибутов, которые не входят в стандартную настройку вариативных продуктов.
Например, у вас есть футболка, где базовая цена 1000 рублей, а при выборе варианта с принтом цена должна увеличиваться на 300 рублей. Стандартный механизм WooCommerce этого не предусматривает напрямую. Решение требует вмешательства через хуки и фильтры.
Диагностика проблемы
- Проверьте, что цены вариаций заданы корректно в админке WooCommerce (Товары > Вариации).
- Убедитесь, что выбранные атрибуты действительно влияют на цену варианта (иногда цена варианта может быть равна базовой).
- Если же необходимо динамически менять цену без создания новых вариаций, стандартного инструментария WooCommerce недостаточно.
Решение: изменение цены вариативного товара через фильтр woocommerce_get_price
Для динамического изменения цены в зависимости от выбранных атрибутов можно использовать фильтр woocommerce_get_price. Ниже приведён пример кода, который добавляет наценку в 300 рублей, если выбран атрибут "Принт" со значением "Да".
add_filter('woocommerce_get_price', 'custom_dynamic_variation_price', 10, 2);function custom_dynamic_variation_price($price, $product) { if (is_admin()) { return $price; // не менять цену в админке } if (!is_product()) { return $price; // только на странице товара } if (!$product->is_type('variation')) { return $price; // только для вариаций } $attributes = $product->get_variation_attributes(); // Проверяем наличие атрибута 'pa_print' со значением 'yes' if (isset($attributes['pa_print']) && $attributes['pa_print'] === 'yes') { $price += 300; } return $price;}Обратите внимание, что в примере атрибут называется pa_print (префикс pa_ — стандарт для пользовательских атрибутов WooCommerce), а значение — yes. Замените на ваши реальные слага и значения.
Обработка цены для отображения на фронте и в корзине
Часто одного фильтра woocommerce_get_price недостаточно. Для корректного отображения цены в корзине, мини-корзине и на странице заказа нужно также использовать фильтры:
woocommerce_get_cart_item_from_sessionдля обновления цены товара в корзине.woocommerce_before_calculate_totalsдля корректировки цены перед подсчётом итогов.
Пример кода для корзины:
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_cart', 20, 1);function custom_dynamic_price_cart($cart) { if (is_admin() && !defined('DOING_AJAX')) return; foreach ($cart->get_cart() as $cart_item) { $product = $cart_item['data']; $attributes = $product->get_variation_attributes(); if (isset($attributes['pa_print']) && $attributes['pa_print'] === 'yes') { $new_price = $product->get_price() + 300; $cart_item['data']->set_price($new_price); } }}Проверка результата после внедрения
- На странице вариативного товара выберите опцию, которая по условию должна изменить цену (в нашем примере — "Принт: Да").
- Цена должна измениться на 300 рублей выше базовой.
- Добавьте товар в корзину и проверьте цену там — она должна соответствовать изменённой цене.
- Оформите заказ и убедитесь, что итоговые суммы совпадают с ожидаемыми.
Частые ошибки и как их исправлять
- Цена не меняется на странице товара: проверьте, что фильтр
woocommerce_get_priceподключён и работает именно для вариаций, а не для простых продуктов. - Цена в корзине не меняется: убедитесь, что добавлен хук
woocommerce_before_calculate_totalsи корректно обновляется цена объекта$cart_item['data']. - Изменения влияют на админку или другие страницы: добавьте проверки
is_admin()иis_product(), чтобы ограничить действие фильтров только фронтендом и страницей товара. - Атрибуты указаны неверно: в WooCommerce атрибуты всегда имеют префикс
pa_, а значения — слагами. Проверьте это в админке (Товары > Атрибуты).
Практические советы по безопасности и производительности
- Не изменяйте цену напрямую в базе данных — используйте только хуки WooCommerce.
- Минимизируйте нагрузку в хуках, избегайте тяжелых операций внутри них.
- Кешируйте результаты, если цена зависит от внешних данных (например, API или сложных вычислений).
- Тестируйте изменения на тестовой копии сайта, чтобы избежать сбоев на рабочем магазине.
Сравнение подходов: стандартные вариации vs динамическое изменение цены
| Подход | Преимущества | Недостатки |
|---|---|---|
| Стандартные вариации WooCommerce | Простота настройки через админку, поддержка всех функций корзины и заказов | Рост количества вариаций при множестве опций, сложность управления |
| Динамическое изменение цены через фильтры | Гибкость настройки, меньше вариаций, можно задать сложные логики | Требует программирования, возможны ошибки без тестирования |