Диагностика задачи: зачем менять стоимость товаров динамически
В WooCommerce часто возникает необходимость менять цену товара не вручную, а автоматически — по условиям, связанным с пользователем, количеством в корзине или другими параметрами. Например, скидка при покупке более 5 единиц, специальные цены для определенных ролей пользователей, или автоматическое обновление цен при акции.
Стандартные возможности WooCommerce не всегда покрывают эти сценарии, поэтому приходится использовать хуки и фильтры для динамического изменения стоимости товара до оформления заказа.
Основные хуки для изменения цены товаров
Для динамического изменения цены в WooCommerce применяются несколько ключевых хуков, которыми можно воспользоваться:
woocommerce_before_calculate_totals— позволяет изменить цену товаров в корзине перед подсчетом итогов.woocommerce_product_get_priceиwoocommerce_product_get_regular_price— фильтры для изменения цены товара при выводе на фронтенде.woocommerce_cart_item_price— для изменения отображаемой цены в корзине.
В подавляющем большинстве случаев для автоматической перерасчета стоимости достаточно использовать woocommerce_before_calculate_totals, т.к. он срабатывает при каждом обновлении корзины.
Пошаговое решение: пример динамического изменения цены по количеству
Рассмотрим пример, когда при покупке более 3 единиц товара цена уменьшается на 10%.
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_discount', 20, 1);
function custom_dynamic_price_discount( $cart ) {
if ( is_admin() && ! defined('DOING_AJAX') ) return; // не меняем в админке
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; // защита от повторного вызова
foreach ( $cart->get_cart() as $cart_item_key => $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 );
}
}
}Этот код нужно добавить в файл functions.php дочерней темы или в отдельный плагин для кастомного функционала.
Как проверить, что цена изменилась
- Добавьте в корзину товар в количестве 1–3 штук — цена должна быть обычной.
- Добавьте 4 и более — цена на фронтенде и в корзине должна уменьшиться на 10%.
- Обновите страницу корзины и убедитесь, что итоговая сумма пересчиталась правильно.
Изменение цены для конкретной роли пользователя
Если нужно менять цены в зависимости от роли пользователя, добавьте проверку роли перед изменением цены:
add_action('woocommerce_before_calculate_totals', 'custom_role_based_price', 20, 1);
function custom_role_based_price( $cart ) {
if ( is_admin() && ! defined('DOING_AJAX') ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
$user = wp_get_current_user();
if ( in_array( 'wholesale_customer', (array) $user->roles ) ) {
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$price = $product->get_regular_price();
$product->set_price( $price * 0.8 ); // скидка 20%
}
}
}Чек-лист для проверки работы динамического изменения цены
- Добавить товар в корзину и проверить цену для разных количеств
- Проверить цены под разными ролями пользователей
- Обновить страницу корзины и убедиться в корректном пересчете
- Проверить, что цена не изменяется в админке и при AJAX-запросах без нужды
- Тестировать на разных устройствах и браузерах
Частые ошибки при динамическом изменении цены в WooCommerce
- Изменение цены в админке: код срабатывает в админ-панели, что приводит к ошибкам. Решение: всегда добавлять проверку
is_admin() && ! defined('DOING_AJAX'). - Повторное срабатывание хука: вызывает бесконечные циклы и сбои. Решение: ограничить вызов с помощью
did_action('woocommerce_before_calculate_totals'). - Использование
set_price()без учета оригинальной цены: цена затирается без возможности возврата. Решение: сохранять оригинальную цену и восстанавливать при необходимости. - Не учитывать кеширование и кэш плагинов: старые цены могут отображаться. Решение: очистить кэш сайта и браузера после внесения изменений.
Практические советы по безопасности и производительности
- Избегайте тяжелых операций в хуках ценообразования, чтобы не замедлять калькуляцию корзины.
- Не храните измененные цены в пользовательских мета, используйте динамические вычисления.
- Используйте фильтры WooCommerce, а не прямое изменение в базе данных, чтобы не нарушить логику работы плагина.
- Тестируйте изменения на стенде перед внедрением на живой сайт, чтобы избежать потери заказов.