Skip to content
  1. Компоненты
  2. MiniShop3
  3. Сниппеты
  4. msCart

msCart ​

Выводит содержимое корзины: список товаров с количеством, ценами и итогами.

Кэширование

Сниппет работает с сессией пользователя и должен вызываться некэшированно.

Параметры ​

ПараметрПо умолчаниюОписание
tpltpl.msCartЧанк оформления корзины
selectorCSS-селектор контейнера для автообновления HTML корзины. При нескольких виджетах корзины укажите его явно (#804, #805)
includeTVsTV-параметры товаров через запятую
includeThumbsПревью изображений через запятую
includeContentВключить поле content товара в выборку
toPlaceholderСохранить результат в плейсхолдер
showLogfalseПоказать журнал выполнения. Виден только тому, кто вошёл в админку
returntplФормат вывода: tpl или data
customer_tokenТокен клиента (по умолчанию из сессии). В properties transport не объявлен (#805)
hideOnThanksfalseПри 1 / true сниппет возвращает пустую строку на странице «спасибо» (она определяется по параметру URL ?msorder=...). При false корзина выводится как обычно — мини-корзина в общем шаблоне продолжает работать. До 1.11.0 пустая строка на этой странице была поведением по умолчанию.

Известные ограничения

toPlaceholder и showLog при части сценариев игнорируются (#803). Параметры sortby / sortdir, если передать, не влияют на порядок позиций (#800).

Параметры pdoTools ​

ПараметрОписание
whereДополнительные условия выборки (JSON)
leftJoinДополнительные JOIN (JSON)
selectДополнительные поля для выборки (JSON)

Порядок товаров не настраивается

Товары выводятся в том порядке, в каком лежат в корзине: сниппет обходит её содержимое, а не делает отсортированную выборку.

Примеры ​

Базовый вывод ​

fenom
{'!msCart' | snippet}

С превью изображений ​

fenom
{'!msCart' | snippet : [
    'includeThumbs' => 'small,medium'
]}

С TV-параметрами ​

fenom
{'!msCart' | snippet : [
    'includeTVs' => 'my_tv,another_tv'
]}

Получение данных в массиве ​

fenom
{var $cart = '!msCart' | snippet : ['return' => 'data']}
{$cart.total.cost} руб.

Вывод в плейсхолдер ​

fenom
{'!msCart' | snippet : [
    'toPlaceholder' => 'cart'
]}

{* Использование *}
{$_modx->getPlaceholder('cart')}

Структура данных корзины ​

При return=data возвращается массив из трёх ключей. Их поля — в таблицах раздела «Плейсхолдеры в чанке».

php
[
    'products' => [
        [
            'product_key' => 'abc123',    // Уникальный ключ позиции
            'id' => 42,                   // ID строки заказа, НЕ товара
            'product_id' => 15,           // ID товара — его и используйте
            'count' => 2,
            'price' => 1500,
            'options' => ['size' => 'M'],
            // ... остальные поля позиции и товара
        ],
        // ...
    ],
    'total'  => [ /* итоги корзины */ ],
    'status' => [ /* агрегаты из Cart::get() */ ],
]

Плейсхолдеры в чанке ​

Товары корзины ​

fenom
{foreach $products as $product}
    {$product.pagetitle} — {$product.count} шт. × {$product.price} руб.
{/foreach}
ПлейсхолдерЗначение
{$product.product_key}Уникальный ключ позиции
{$product.product_id}ID товара. Ссылка на карточку: {$product.product_id | url}
{$product.id}ID строки заказа, а не товара. Ссылку по нему строить нельзя
{$product.count}Количество
{$product.price}Цена за единицу
{$product.weight}Вес за единицу
{$product.old_price}Старая цена
{$product.discount_price}Скидка на единицу
{$product.discount_cost}Скидка на позицию (количество × скидка)
{$product.price_formatted}Цена с валютой (например 1 234 ₽)
{$product.old_price_formatted}Старая цена с валютой
{$product.cost_formatted}Стоимость позиции с валютой
{$product.old_cost_formatted}Старая стоимость позиции с валютой
{$product.weight_formatted}Вес с единицей (например 500 г)
{$product.discount_price_formatted}Скидка на единицу с валютой
{$product.discount_cost_formatted}Скидка на позицию с валютой
{$product.options}Массив опций
{$product.option_*}Опции как отдельные поля (например option_size)

Кроме них доступны все поля товара (pagetitle, article, thumb и другие) и поля производителя. Имена полей производителя содержат точку — это плоские ключи, а не вложенный массив, поэтому пишите {$product['vendor.name']}, а не {$product.vendor.name}.

Итоги ​

ПлейсхолдерЗначение
{$total.count}Общее количество товаров
{$total.positions}Количество позиций (уникальных товаров)
{$total.weight}Общий вес
{$total.cost}Общая стоимость
{$total.discount}Сумма скидок
{$total.cost_formatted}Стоимость с символом валюты
{$total.weight_formatted}Вес с единицей измерения

Статус корзины ​

Начиная с v1.9.0, в чанке и при return=data доступен массив status — данные из Cart::get() после обработки плагинами.

ПлейсхолдерЗначениеСинхронизируется с
{$status.total_count}Количество товаровtotal.count
{$status.total_cost}Итоговая стоимость (с учётом плагинов)total.cost
{$status.total_weight}Общий весtotal.weight
{$status.total_discount}Сумма скидокtotal.discount
{$status.total_positions}Количество позицийtotal.positions

Синхронизация с плагинами

Если плагин на событие msOnGetStatusCart изменяет агрегаты в status (например, пересчитывает скидку или добавляет стоимость доставки), сниппет автоматически синхронизирует total с данными status. Поля из третьей колонки будут соответствовать значениям из status, а не простой сумме по строкам корзины.

Автообновление HTML ​

Сниппет регистрируется через registerSnippet() для перерисовки при изменении корзины (как msOrderTotal). Укажите selector, если на странице несколько блоков корзины:

fenom
<div id="sidebar-cart">
    {'!msCart' | snippet : [
        'selector' => '#sidebar-cart'
    ]}
</div>

Пример чанка ​

fenom
{* tpl.msCart *}
<div class="ms-cart">
    {if $products?}
        <table class="cart-table">
            <thead>
                <tr>
                    <th>Товар</th>
                    <th>Цена</th>
                    <th>Количество</th>
                    <th>Сумма</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                {foreach $products as $product}
                    <tr id="{$product.product_key}">
                        <td>
                            {if $product.thumb?}
                                <img src="{$product.thumb}" alt="{$product.pagetitle}">
                            {/if}
                            <a href="{$product.product_id | url}">{$product.pagetitle}</a>

                            {if $product.options?}
                                <small>
                                    {foreach $product.options as $key => $value}
                                        {$key}: {$value}{if !$value@last}, {/if}
                                    {/foreach}
                                </small>
                            {/if}
                        </td>
                        <td>
                            {if $product.old_price > 0}
                                <del>{$product.old_price_formatted}</del>
                            {/if}
                            {$product.price_formatted}
                        </td>
                        <td>
                            {* Изменение количества — формой: скрипт читает ms3_action внутри неё *}
                            <form method="post" class="ms3_form" data-ms3-form>
                                <input type="hidden" name="product_key" value="{$product.product_key}">
                                <input type="hidden" name="ms3_action" value="cart/change">
                                <input type="number" name="count" value="{$product.count}" min="0">
                            </form>
                        </td>
                        <td>{$product.cost_formatted}</td>
                        <td>
                            <form method="post" class="ms3_form" data-ms3-form>
                                <input type="hidden" name="product_key" value="{$product.product_key}">
                                <input type="hidden" name="ms3_action" value="cart/remove">
                                <button type="submit">&times;</button>
                            </form>
                        </td>
                    </tr>
                {/foreach}
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="3">Итого:</td>
                    <td colspan="2">
                        <strong>{$total.cost_formatted}</strong>
                    </td>
                </tr>
            </tfoot>
        </table>

        {set $order_page_id = 'ms3_order_page_id' | option}
        <a href="{$order_page_id | url}" class="btn btn-primary">
            Оформить заказ
        </a>
    {else}
        <p>Корзина пуста</p>
    {/if}
</div>

Работа из JavaScript ​

javascript
// Добавить товар
await ms3.cartAPI.add(productId, count, options)

// Изменить количество
await ms3.cartAPI.change(productKey, count)

// Удалить товар
await ms3.cartAPI.remove(productKey)

// Очистить корзину
await ms3.cartAPI.clean()

cartAPI не перерисовывает разметку

Это только обращение к серверу. HTML корзины не обновится и событие ms3:cart:updated не сработает — ни у одного из методов, не только у clean(). Перерисовкой занимается ms3.cartUI: например, ms3.cartUI.handleClean() вместо прямого вызова cartAPI.clean().

События ​

При изменении корзины срабатывает событие:

javascript
document.addEventListener('ms3:cart:updated', function(e) {
    console.log('Корзина обновлена:', e.detail);
});

Разметка действий с корзиной ​

Действия описываются формой с классом ms3_form и скрытым полем ms3_action, а позиция адресуется полем product_key. Полный разбор разметки, таблица допустимых действий и примеры форм — на странице Корзина.