WooCommerce: как изменить стоимость товаров в корзине без пересчета

Диагностика проблемы: зачем изменять стоимость в корзине без пересчета

В WooCommerce при изменении цены товара в корзине по умолчанию происходит автоматический пересчет всех сумм. Это некритично при стандартных скидках, но когда требуется динамическое изменение цены на уровне корзины (например, особые наценки, скидки или корректировки, зависящие от внешних условий), стандартное поведение мешает сохранить нужную стоимость без влияния на другие позиции.

Типичные задачи, в которых требуется такой функционал:

  • Применение индивидуальных скидок, не влияющих на базовую цену товара;
  • Изменение цены в зависимости от пользовательского выбора, не меняя стоимость в базе данных;
  • Корректировка цены в корзине для специальных условий оплаты или доставки.

Как WooCommerce рассчитывает стоимость товаров в корзине

WooCommerce использует объект WC_Cart с массивом элементов корзины $cart->cart_contents. Каждый элемент — массив с данными товара, включая цену data->get_price() и цену в корзине $cart_item['data']->set_price(). При обновлении корзины запускается пересчет всех позиций и итогов.

Чтобы изменить стоимость без пересчета, нужно работать именно с объектом товара в корзине, задавая цену напрямую, но избегая стандартных триггеров пересчета.

Пошаговое решение: изменение цены в корзине через хук woocommerce_before_calculate_totals

Самый надежный способ — использовать хук woocommerce_before_calculate_totals, который вызывается непосредственно при расчёте итогов корзины. В этом хук можно программно изменить цену товара, и WooCommerce автоматически учтет новые значения без лишних пересчетов.

Пример кода для изменения цены товара с ID 123 на 500 рублей:

add_action('woocommerce_before_calculate_totals', 'custom_change_cart_item_price', 20, 1);
function custom_change_cart_item_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        if ( $cart_item['product_id'] == 123 ) {
            $cart_item['data']->set_price( 500 );
        }
    }
}

Обратите внимание, что цена меняется только в корзине и на странице оформления заказа, базовая цена товара в каталоге и в базе данных остается неизменной.

Изменение цены для нескольких товаров с разными условиями

Если нужно менять цены для нескольких товаров по разным правилам, лучше оформить их в массив с ID и нужными ценами:

add_action('woocommerce_before_calculate_totals', 'custom_bulk_change_cart_prices', 20, 1);
function custom_bulk_change_cart_prices( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

    $price_overrides = [
        123 => 500,
        456 => 750,
        789 => 300,
    ];

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product_id = $cart_item['product_id'];
        if ( isset( $price_overrides[$product_id] ) ) {
            $cart_item['data']->set_price( $price_overrides[$product_id] );
        }
    }
}

Как проверить, что решение работает

  • Добавьте товар с ID 123 в корзину.
  • Перейдите в корзину — цена должна измениться на 500 рублей.
  • Перейдите к оформлению заказа — цена сохраняется.
  • Вернитесь в каталог — цена товара не изменилась.
  • Попробуйте добавить другие товары — их цена не меняется, если не прописано в коде.

Частые ошибки и как их исправить

  • Изменение цены вне хука woocommerce_before_calculate_totals: приводит к некорректному пересчету итогов или игнорированию изменений.
  • Не проверка условий is_admin() и DOING_AJAX: изменение цены в административной части или при AJAX-запросах вызывает ошибки и неверное отображение.
  • Использование $cart->cart_contents напрямую без вызова get_cart(): меньше гибкости и потенциальные проблемы при обновлениях WooCommerce.
  • Попытка изменить цену товара напрямую в базе: не влияет на корзину и вызывает рассинхронизацию.
  • Забыли отключить кэширование страницы корзины: изменения не видны из-за кэширования.

Практические советы по производительности и безопасности

  • Обязательно фильтруйте товары по ID или другим параметрам, чтобы не менять цену всех товаров без причины.
  • Добавляйте защиту от изменений в админке, чтобы не сломать работу сайта.
  • Минимизируйте количество вычислений в хуке — используйте кэширование или глобальные параметры.
  • Не храните измененную цену в пользовательских мета — меняйте только в объекте товара в корзине.

Сравнение способов изменения цены в корзине

СпособОписаниеПлюсыМинусы
Хук woocommerce_before_calculate_totalsИзменение цены через $cart_item['data']->set_price() перед расчетом суммы.Надежно, поддерживается WooCommerce, влияет только на корзину.Требует понимания работы корзины, не изменяет базу данных.
Изменение цены через фильтр woocommerce_product_get_priceГлобальное изменение цены товара при вызове get_price().Меняет цену во всех местах, гибко.Может повлиять на каталог, оформление заказа, что не всегда нужно.
Прямое изменение базы данныхОбновление цены товара в таблице wp_postmeta.Постоянное изменение цены.Небезопасно, влияет на все места, требует отката.
WooCommerce: как автоматически удалять старые корзины покупателей
13.06.2026
Как создать динамический шаблон для WooCommerce с кастомным выводом товаров
17.02.2026
Как отключить редактор Gutenberg в WordPress 5.9: практические способы и примеры
08.03.2026
Как создать отзывы с оценками в WordPress
20.02.2026
Как удалить избыточные CSS и JS в WordPress и улучшить скорость загрузки
28.12.2025