Диагностика задачи: зачем менять цены динамически в WooCommerce
В интернет-магазине на WooCommerce часто возникает необходимость менять цены на товары в зависимости от условий: скидки для определённых пользователей, акции, специальные предложения, динамическое ценообразование на основе количества товаров в корзине и др. Стандартных настроек WooCommerce для гибкого динамического изменения цен может не хватать. В таком случае пригодятся хуки WooCommerce для программного изменения цены товара прямо во время отображения страницы или оформления заказа.
Какие хуки использовать для изменения цены товара
Самые распространённые фильтры WooCommerce для изменения цены товара — это:
woocommerce_product_get_price— фильтр изменения цены товара при получении;woocommerce_product_get_regular_price— для изменения базовой цены товара;woocommerce_product_get_sale_price— для изменения цены со скидкой;woocommerce_cart_item_price— для изменения цены товара в корзине;woocommerce_before_calculate_totals— хук для изменения цены товара в корзине перед подсчетом итогов.
Почему использовать woocommerce_before_calculate_totals для динамической цены в корзине
Этот хук позволяет изменить цену товара в объекте корзины перед подсчетом итоговой суммы заказа. Изменения через другие фильтры часто не влияют на итоговую сумму, если не изменять цену именно в корзине.
Пошаговое решение: пример кода для динамического изменения цены в корзине
Допустим, нужно сделать скидку 10% для всех товаров в корзине пользователям с ролью "подписчик".
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_for_subscribers', 10, 1);
function custom_dynamic_price_for_subscribers($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
// Проверяем роль пользователя
if (!is_user_logged_in()) {
return;
}
$user = wp_get_current_user();
if (in_array('subscriber', (array) $user->roles)) {
// Проходимся по товарам в корзине
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$original_price = $product->get_regular_price();
$discounted_price = $original_price * 0.9; // скидка 10%
$product->set_price($discounted_price);
}
}
}Этот код добавляется в файл functions.php темы или в кастомный плагин.
Другой пример: изменение цены по количеству товара в корзине
add_action('woocommerce_before_calculate_totals', 'bulk_discount_based_on_quantity', 10, 1);
function bulk_discount_based_on_quantity($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$quantity = $cart_item['quantity'];
$product = $cart_item['data'];
$price = $product->get_regular_price();
if ($quantity >= 5) { // скидка 15% при покупке 5 и более
$new_price = $price * 0.85;
$product->set_price($new_price);
} else {
$product->set_price($price);
}
}
}Как проверить, что динамическое изменение цены сработало
- Добавьте товар в корзину под учётной записью пользователя с нужной ролью (например, подписчик).
- Откройте страницу корзины — цена товара должна измениться согласно условию.
- Проверьте, что итоговая сумма заказа учитывает новую цену.
- Для отладки можно временно добавить
error_logс выводом цены внутри функции.
Частые ошибки при изменении цены через хуки WooCommerce и как их исправить
- Цена меняется на всех страницах, включая админку: всегда проверяйте
is_admin()иDOING_AJAX, чтобы не сломать админку.
Правильно:if (is_admin() && !defined('DOING_AJAX')) return; - Изменения цены не влияют на итоговую сумму: меняйте цену через
woocommerce_before_calculate_totals, а не только через фильтры получения цены товара.
Цена меняется только в объекте корзины. - Цена сбрасывается при обновлении или переходе: убедитесь, что функция навешана на правильный хук с приоритетом, и что цена устанавливается при каждом вызове.
- Ошибки вывода или конфликты с другими плагинами: тестируйте на чистом сайте, отключайте другие плагины для локализации проблемы.
Практические советы по безопасности и производительности
- Не меняйте цену товара глобально — меняйте только копию объекта товара в корзине, чтобы не ломать базу данных.
- Избегайте тяжелых запросов и сложных расчетов внутри хука — используйте кеширование, если данные берутся из внешних источников.
- Проверяйте роль пользователя и другие условия только когда это необходимо, чтобы не создавать излишнюю нагрузку.
- Тестируйте работу на разных этапах оформления заказа, чтобы избежать проблем с оплатой и расчётами.
Сравнение способов изменения цены в WooCommerce
| Способ | Когда использовать | Плюсы | Минусы |
|---|---|---|---|
woocommerce_product_get_price | Отображение цены на странице товара | Легко изменить отображаемую цену | Не влияет на итоговую сумму заказа |
woocommerce_before_calculate_totals | Изменение цены в корзине и оформлении заказа | Изменяет фактическую сумму и цену в заказе | Сложнее в реализации, требует аккуратности |
| Плагины динамического ценообразования | Сложные правила и большие магазины | Много готовых функций и настроек | Платные, могут конфликтовать с кастомным кодом |