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.Постоянное изменение цены.Небезопасно, влияет на все места, требует отката.
Как создать собственный плагин для WordPress с примерами кода
02.12.2025
Добавление поля телефона с подтверждением в форму регистрации WordPress
19.03.2026
Создаем свой шаблон для WordPress с нуля
04.11.2025
Как удалить или заблокировать плагин WordPress, если стандартные методы не работают
24.01.2026
Удаление и блокировка плагинов WordPress, если стандартные методы не работают
16.01.2026