Диагностика задачи: зачем и когда нужно менять цену товара автоматически
В WooCommerce иногда возникает необходимость менять цену товара программно в зависимости от определённых условий: например, по количеству в корзине, роли пользователя, дате покупки или других параметрах. Это позволяет гибко управлять ценообразованием без ручного редактирования каждого товара.
Стандартный функционал WooCommerce для скидок и акций ограничен, а плагины могут не подходить по функционалу или вызывать конфликт. Поэтому решение через кастомный код — оптимальный вариант.
Пошаговое решение: как автоматически изменять цену товара
1. Используем хук woocommerce_before_calculate_totals
Этот хук срабатывает перед подсчётом итоговой стоимости корзины и позволяет изменить цену товара динамически.
2. Пример кода для изменения цены товара по количеству
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_change', 20, 1);
function custom_dynamic_price_change( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
// Пробегаем по всем товарам в корзине
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$quantity = $cart_item['quantity'];
// Пример условия: если куплено 5 и более товаров, цена уменьшается на 10%
if ( $quantity >= 5 ) {
$original_price = $product->get_regular_price();
$new_price = $original_price * 0.9; // скидка 10%
$product->set_price( $new_price );
} else {
// Важно вернуть цену к оригиналу, если условие не выполняется
$product->set_price( $product->get_regular_price() );
}
}
}3. Как изменить цену по роли пользователя
add_action('woocommerce_before_calculate_totals', 'custom_price_based_on_user_role', 20, 1);
function custom_price_based_on_user_role( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( ! is_user_logged_in() ) return;
$user = wp_get_current_user();
$roles = (array) $user->roles;
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
if ( in_array( 'wholesale_customer', $roles ) ) {
// Оптовая цена 20% ниже
$new_price = $product->get_regular_price() * 0.8;
$product->set_price( $new_price );
} else {
$product->set_price( $product->get_regular_price() );
}
}
}Проверка результата после внедрения
- Добавьте в корзину нужное количество товара и проверьте, изменяется ли цена в соответствии с условием.
- Если меняете цену по роли — войдите под соответствующим пользователем и повторите добавление товара в корзину.
- Проверьте итоговую сумму заказа на странице оформления заказа и в админке WooCommerce.
- Для отладки можно добавить
error_logилиvar_dump, чтобы убедиться, что условие срабатывает.
Частые ошибки и как их исправить
- Цена не меняется: убедитесь, что хук подключён правильно и приоритет 20 установлен (раньше может не сработать). Проверьте, что код не выполняется в админке.
- Цена сбрасывается в конце: важно всегда возвращать цену к оригинальной, если условие не выполняется, иначе цена может остаться изменённой для следующих товаров.
- Конфликты с кешированием: кэш страниц или объектов может показывать старые цены — очистите кэш и отключите кеширование для теста.
- Изменение цены не сохраняется при AJAX обновлении корзины: убедитесь, что хук поддерживает AJAX, и код не блокирует ajax-запросы.
- Изменения цены влияют на отпечатки корзины (session hash): если используете сторонние плагины кеширования, проверьте совместимость.
Практические советы по безопасности и производительности
- Не используйте глобальные переменные и минимизируйте обращение к базе данных внутри хука.
- Проверяйте роль пользователя и количество товаров один раз за вызов, а не для каждого товара.
- Используйте
is_admin() && ! defined( 'DOING_AJAX' )для предотвращения избыточного выполнения в админке. - Для сложных условий лучше использовать transient или кеширование, чтобы не нагружать сервер при каждом обновлении корзины.
Таблица сравнения вариантов реализации изменения цены в WooCommerce
| Способ | Плюсы | Минусы | Пример использования |
|---|---|---|---|
Код через woocommerce_before_calculate_totals | Гибкий, без плагинов, контролируемый | Требует навыков программирования, возможны ошибки | Изменение цены по количеству или роли |
| Плагины скидок и динамического ценообразования | Удобно, много функций, интерфейс | Может нагружать сайт, конфликтовать, платные | WooCommerce Dynamic Pricing, Discount Rules |
| Создание отдельного товара с нужной ценой | Просто, без кода | Много товаров, неудобно управлять | Для статических скидок |