Как разделить корзину WooCommerce по классам доставки и не сломать оформление заказа

Сценарий типичный: в корзине оказываются товары с разными классами доставки, а магазин должен либо показать их отдельными группами, либо не давать оформить заказ в одном чекауте без явного разделения. Чаще всего проблема всплывает после настройки тарифов доставки, подключения нескольких складов или когда часть ассортимента отправляется курьером, а часть — только самовывозом.

Если просто пытаться «спрятать» товары в интерфейсе корзины, можно получить побочные эффекты: неверный расчет доставки, дубли в итогах, ошибки при применении купонов и некорректные письма клиенту. Поэтому лучше решать задачу на уровне логики корзины, а не только верстки.

Когда это действительно нужно

Разделение корзины по классам доставки полезно, если у вас есть хотя бы один из этих сценариев:

  • товары с разными способами отправки нельзя отправить одной посылкой;
  • часть ассортимента должна оформляться отдельно из-за разных складов;
  • доставка зависит не только от зоны, но и от типа товара;
  • нужно явно показать клиенту, что в заказе есть несколько групп с разной логистикой;
  • менеджеру важно видеть, какие позиции относятся к какому способу доставки.

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

Перед изменением логики корзины проверьте базовые настройки WooCommerce. Часто проблема не в теме и не в шаблоне, а в конфигурации доставки.

Проверьте классы доставки у товаров

Убедитесь, что у нужных товаров действительно назначены shipping class. Если класс не задан, фильтровать корзину по нему бессмысленно: товар попадет в «общую» группу.

Проверьте зоны и методы доставки

Если у вас несколько зон доставки, сначала убедитесь, что WooCommerce корректно считает тарифы без кастомного кода. Иначе вы будете лечить не ту проблему. Для теста добавьте в корзину по одному товару из каждой группы и посмотрите, как меняется блок доставки на чекауте.

Проверьте, не вмешивается ли плагин кэширования

Кэш корзины и мини-корзины иногда маскирует изменения. Если после правок вы не видите разницы, временно отключите оптимизацию фрагментов корзины и очистите кэш страницы оформления заказа.

Подходы к решению: плагин, код, компромисс

ПодходЧто даетМинус
Плагин для логики доставкиБыстрее запуск, меньше кодаМожет быть избыточным для простой задачи
Код в дочерней теме или мини-плагинеПолный контроль над корзиной и чекаутомНужно тестировать после обновлений WooCommerce
Компромисс: код только для валидацииНе ломает интерфейс, но ограничивает оформлениеПользователь увидит ошибку уже на чекауте

Если задача точечная, я бы не начинал с тяжелого плагина. Для большинства магазинов достаточно небольшой проверки на этапе оформления заказа и понятного сообщения клиенту.

Пошаговое решение через код

Ниже пример, который не пытается физически «разрезать» корзину на две отдельные корзины, а проверяет состав заказа и запрещает оформление, если в корзине смешаны товары с разными классами доставки. Это безопаснее, чем вмешиваться в расчет totals и ломать купоны или налоги.

<?php
add_action( 'woocommerce_check_cart_items', 'wptemplates_validate_shipping_classes_in_cart' );

function wptemplates_validate_shipping_classes_in_cart() {
    if ( ! WC()->cart || WC()->cart->is_empty() ) {
        return;
    }

    $classes = array();

    foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( empty( $cart_item['data'] ) || ! is_object( $cart_item['data'] ) ) {
            continue;
        }

        $product = $cart_item['data'];
        $class_id = $product->get_shipping_class_id();

        if ( $class_id ) {
            $classes[ $class_id ] = true;
        }
    }

    if ( count( $classes ) > 1 ) {
        wc_add_notice(
            'В корзине есть товары с разными классами доставки. Разделите заказ или оформите позиции отдельно.',
            'error'
        );
    }
}

Этот вариант подходит, если бизнес-правило жесткое: смешивать товары нельзя. Если же нужно не запрещать заказ, а только группировать позиции для менеджера, логика будет другой.

Если нужно только пометить группы в корзине

Иногда достаточно вывести рядом с каждой позицией ее класс доставки. Это помогает менеджеру и клиенту понять, почему доставка считается отдельно, но не мешает оформлению.

<?php
add_filter( 'woocommerce_get_item_data', 'wptemplates_show_shipping_class_in_cart', 10, 2 );

function wptemplates_show_shipping_class_in_cart( $item_data, $cart_item ) {
    if ( empty( $cart_item['data'] ) || ! is_object( $cart_item['data'] ) ) {
        return $item_data;
    }

    $product = $cart_item['data'];
    $class_id = $product->get_shipping_class_id();

    if ( ! $class_id ) {
        return $item_data;
    }

    $term = get_term( $class_id, 'product_shipping_class' );

    if ( $term && ! is_wp_error( $term ) ) {
        $item_data[] = array(
            'name'  => 'Класс доставки',
            'value' => $term->name,
        );
    }

    return $item_data;
}

Такой подход не меняет расчет корзины и обычно безопаснее для магазинов, где уже настроены купоны, налоги и несколько способов доставки.

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

После внедрения проверьте не только визуальный результат, но и поведение checkout.

  • Добавьте в корзину товары из одного класса доставки и убедитесь, что заказ проходит.
  • Добавьте товар из другого класса и проверьте, появляется ли предупреждение или метка.
  • Откройте страницу оформления заказа в режиме инкогнито, чтобы исключить влияние кэша и сохраненной сессии.
  • Проверьте письма WooCommerce: в них должны корректно отображаться позиции и их названия.
  • Если используете купоны, протестируйте применение скидки до и после изменения логики.

Для быстрой диагностики можно временно вывести в лог список классов доставки, которые попали в корзину. Это проще, чем гадать по интерфейсу.

<?php
add_action( 'woocommerce_check_cart_items', function() {
    if ( ! WC()->cart ) {
        return;
    }

    $classes = array();

    foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( ! empty( $cart_item['data'] ) ) {
            $classes[] = $cart_item['data']->get_shipping_class_id();
        }
    }

    error_log( 'Cart shipping classes: ' . implode( ',', array_filter( $classes ) ) );
} );

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

Проверяют не тот объект товара

В корзине нужно работать с объектом из $cart_item['data'], а не с ID товара напрямую. Иначе методы WooCommerce, включая get_shipping_class_id(), будут недоступны.

Считают, что вариация наследует класс автоматически

У вариативных товаров класс доставки может быть задан на уровне вариации или родительского товара, и это нужно проверить отдельно. Если логика строится на классе доставки, тестируйте именно вариации, а не только базовый товар.

Пытаются менять totals вручную

Если вмешиваться в сумму корзины через woocommerce_before_calculate_totals без четкой причины, легко сломать налоги, купоны и повторный расчет. Для задачи разделения по доставке это обычно лишнее.

Не очищают кэш и фрагменты корзины

После правок в логике доставки старые фрагменты мини-корзины могут показывать устаревшие данные. Очистите кэш страницы, объектный кэш и проверьте поведение без оптимизаторов JavaScript.

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

Если решение идет в продакшн, лучше вынести код в мини-плагин или дочернюю тему, а не править файлы родительской темы. Так вы не потеряете изменения при обновлении.

Еще два момента, которые реально важны:

  • не добавляйте тяжелые запросы к базе внутри цикла по товарам в корзине;
  • не используйте логику, которая каждый раз дергает внешние API на странице checkout;
  • проверяйте, как решение работает на мобильном чекауте, где ошибки валидации заметнее;
  • если магазин большой, тестируйте на staging-копии с реальными типами товаров и купонами.

Если вам нужно не просто ограничить оформление, а построить более сложную логику доставки, иногда проще подключить специализированный плагин для shipping rules, чем поддерживать большой кастомный код. Но для узкой задачи с классами доставки код обычно быстрее, прозрачнее и легче отлаживается.

Как использовать AJAX в WordPress для обновления шаблонов без перезагрузки страницы
13.02.2026
Автоматизация установки и настройки темы WordPress: пошаговое руководство
16.03.2026
WooCommerce: как изменить стоимость товаров в корзине без пересчета
29.05.2026
Как создать адаптивный шаблон WordPress без фреймворков
14.11.2025
Как добавить автоматическое сохранение в редактор Gutenberg WordPress
23.02.2026