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

msCustomer ​

Выводит личный кабинет покупателя. Параметр service выбирает раздел: profile, addresses или orders.

Страница кабинета не должна кэшироваться

Снимите у ресурса галочку «Кэшировать» в админке. Сниппет выводит данные конкретного покупателя; на кэшируемой странице они сохранятся в кэше и достанутся следующему посетителю.

Префикса ! для этого недостаточно. В MODX [[!msCustomer]] откладывает исполнение до некэшируемого прохода, а в Fenom {'!msCustomer'|snippet} сниппет выполняется там же, где встретился. Префикс лишь отключает кэш элемента в pdoTools: ставить его стоит, но полагаться — только на настройку ресурса.

Принцип работы ​

Вызов и параметры ​

Общие параметры ​

ПараметрПо умолчаниюОписание
serviceprofileРаздел: profile, addresses, orders
returntplФормат: tpl (HTML), data (массив)
unauthorizedTpltpl.msCustomer.unauthorizedЧанк для неавторизованных

Свойств сниппета в админке нет

У msCustomer не объявлено ни одного свойства, поэтому в сетке свойств сниппета пусто: все параметры задаются только в вызове. Так же обстоит дело с selector у msCart и msOrderTotal (#805).

Профиль покупателя (service=profile) ​

Правка личных данных: имя, email, телефон и статусы их подтверждения.

fenom
{'!msCustomer' | snippet : [
    'service' => 'profile'
]}
ПараметрПо умолчаниюОписание
tpltpl.msCustomer.profileЧанк профиля

Подробнее: Профиль покупателя

Адреса доставки (service=addresses) ​

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

fenom
{'!msCustomer' | snippet : [
    'service' => 'addresses'
]}
ПараметрПо умолчаниюОписание
tpltpl.msCustomer.addressesЧанк списка адресов
addressTpltpl.msCustomer.address.rowЧанк строки адреса
formTpltpl.msCustomer.address.formЧанк формы адреса

Подробнее: Адреса доставки

История заказов (service=orders) ​

Заказы покупателя: фильтр по статусу, пагинация, детали заказа. Черновики (статус с id=1) не попадают ни в список, ни в фильтр статусов.

fenom
{'!msCustomer' | snippet : [
    'service' => 'orders',
    'limit' => 10
]}
ПараметрПо умолчаниюОписание
tpltpl.msCustomer.ordersЧанк списка заказов
orderTpltpl.msCustomer.order.rowЧанк строки заказа
detailTpltpl.msCustomer.order.detailsЧанк деталей заказа
limit20Заказов на странице

Подробнее: История заказов

Получение данных в массиве (return=data) ​

fenom
{set $profile = '!msCustomer' | snippet : [
    'service' => 'profile',
    'return' => 'data'
]}

{if $profile.authorized}
    Привет, {$profile.customer.first_name}!
{else}
    <a href="{$profile.login_url}">Войти</a>
{/if}

GET-параметры ​

ПараметрСервисОписание
action=logoutлюбойВыход из кабинета
orderordersUUID заказа (36 символов) — показать детали
statusordersФильтр по ID статуса
offsetordersСмещение для пагинации
modeaddressesРежим: list, edit, create
idaddressesID адреса для mode=edit
text
/cabinet/?action=logout                               — выход из кабинета
/cabinet/?order=0f9e8d7c-1a2b-3c4d-5e6f-7a8b9c0d1e2f  — детали заказа
/cabinet/?status=2                                    — заказы со статусом 2
/cabinet/?offset=20                                   — вторая страница
/cabinet/addresses/                                   — список адресов
/cabinet/addresses/?mode=create                       — создание адреса
/cabinet/addresses/?mode=edit&id=5                    — правка адреса #5

Структура данных ​

Профиль (service=profile) ​

php
[
    'authorized' => true,
    'service' => 'profile',
    'customer' => [
        'id' => 1,
        'email' => 'user@example.com',
        'first_name' => 'Иван',
        'last_name' => 'Иванов',
        'phone' => '+7 999 123-45-67',
        // ... другие поля msCustomer
    ],
    'email_verified' => true,
    'email_verified_at' => '15.01.2024 12:30',
    'phone_verified' => false,      // всегда false, см. #138
    'phone_verified_at' => null,
    'errors' => [],
    'success' => false,
]

Список заказов (service=orders) ​

php
[
    'authorized' => true,
    'service' => 'orders',
    'orders' => [
        [
            'id' => 15,
            'num' => '2610/5',
            'createdon' => '2024-01-15 10:30:00',
            'createdon_formatted' => '15.01.2024 10:30',
            'cost' => 7500,
            'cost_formatted' => '7 500',
            'status_id' => 2,
            'status_name' => 'Оплачен',
            'status_color' => '008000',
            'can_cancel' => false,
            // ... другие поля msOrder
        ],
        // ...
    ],
    'orders_count' => 5,
    'total' => 12,
    'statuses' => [
        ['id' => 2, 'name' => 'Оплачен', 'color' => '008000', 'selected' => false],
        ['id' => 3, 'name' => 'Отправлен', 'color' => '0000FF', 'selected' => false],
    ],
    'pagination' => [
        'total' => 12,
        'total_pages' => 2,
        'current_page' => 1,
        'limit' => 10,
        'offset' => 0,
        'pages' => [...],
        'has_prev' => false,
        'has_next' => true,
        'prev_offset' => 0,
        'next_offset' => 10,
    ],
    'customer' => [...],
    'page_url' => 'https://example.com/cabinet/',
]

Детали заказа (service=orders) ​

При наличии GET-параметра order:

php
[
    'authorized' => true,
    'service' => 'orders',
    'order' => [
        'id' => 15,
        'num' => '2610/5',
        'status_name' => 'Оплачен',
        'status_color' => '008000',
        'createdon_formatted' => '15.01.2024 10:30',
        'can_cancel' => false,
        'order_comment' => 'Позвонить перед доставкой',
        // ... другие поля msOrder
    ],
    'products' => [
        [
            'product_id' => 10,
            'pagetitle' => 'Товар 1',
            'article' => 'ART-001',
            'count' => 2,
            'price' => '3 500',
            'old_price' => '4 000',
            'cost' => '7 000',
            'weight' => '500',
            'weight_formatted' => '500 г',
            'options' => ['color' => 'Красный', 'size' => 'M'],
        ],
        // ...
    ],
    'delivery' => [
        'id' => 1,
        'name' => 'Курьерская доставка',
        'description' => 'Доставка в течение 1-2 дней',
    ],
    'payment' => [
        'id' => 2,
        'name' => 'Банковская карта',
    ],
    'address' => [
        'city' => 'Москва',
        'street' => 'ул. Примерная',
        'building' => '15',
        'room' => '42',
        // ... другие поля адреса
    ],
    'total' => [
        'cost' => '7 800',
        'cart_cost' => '7 500',
        'delivery_cost' => '300',
        'weight' => '1',
        'weight_formatted' => '1 кг',
    ],
    'customer' => [...],
    'api_url' => '/api/v1/',
    'assets_url' => '/assets/components/minishop3/',
]

Если заказ не найден или принадлежит другому покупателю:

php
[
    'error' => 'Заказ не найден',
    'customer' => [...],
]

Неавторизованный пользователь ​

php
[
    'authorized' => false,
    'login_url' => '/login/',       // пусто, пока не задан ms3_customer_login_page_id
    'register_url' => '/register/', // пусто, пока не задан ms3_customer_register_page_id
]

Архитектура чанков ​

Чанки разделов расширяют базовый чанк и заполняют в нём блок content:

text
tpl.msCustomer.base          — базовый layout (sidebar + content)
├── tpl.msCustomer.profile   — extends base, блок профиля
├── tpl.msCustomer.orders    — extends base, блок списка заказов
└── tpl.msCustomer.addresses — extends base, блок адресов
fenom
{* tpl.msCustomer.base *}
<div class="ms3-customer-account">
    <div class="container">
        <div class="row">
            <div class="col-lg-3 col-md-4 mb-4">
                {include 'tpl.msCustomer.sidebar'}
            </div>
            <div class="col-lg-9 col-md-8">
                {block 'content'}{/block}
            </div>
        </div>
    </div>
</div>

Штатные чанки разделов целиком — на страницах Профиль покупателя, Адреса доставки и История заказов. Обязательная разметка формы — в разделе Обработка форм.

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

tpl.msCustomer.profile ​

ПлейсхолдерОписание
{$customer}Данные покупателя (массив)
{$customer.id}ID покупателя
{$customer.email}Email
{$customer.first_name}Имя
{$customer.last_name}Фамилия
{$customer.phone}Телефон
{$email_verified}Email подтверждён (bool)
{$email_verified_at}Дата подтверждения email
{$phone_verified}Всегда false — подтверждение телефона запланировано (#138)
{$phone_verified_at}Всегда пусто, по той же причине
{$errors}Ошибки валидации (массив)
{$success}Успешное сохранение (bool)

tpl.msCustomer.order.row ​

ПлейсхолдерОписание
{$id}ID заказа
{$num}Номер заказа. Дата по ms3_order_format_num плюс разделитель и счётчик — например, 2610/5
{$createdon_formatted}Дата создания
{$cost_formatted}Сумма заказа
{$status_name}Название статуса
{$status_color}Цвет статуса

Плейсхолдеры остальных чанков, с типами значений: История заказов — tpl.msCustomer.orders и tpl.msCustomer.order.details; Адреса доставки — список и форма адреса.

Системные настройки ​

НастройкаОписание
ms3_customer_login_page_idID страницы входа
ms3_customer_register_page_idID страницы регистрации
ms3_customer_profile_page_idID страницы профиля
ms3_customer_orders_page_idID страницы истории заказов
ms3_customer_addresses_page_idID страницы адресов
ms3_customer_cancel_allowed_statusesID статусов, из которых покупатель может отменить заказ, через запятую

Страницы кабинета нужно указать в настройках

В поставке ms3_customer_login_page_id, ms3_customer_register_page_id, ms3_customer_profile_page_id, ms3_customer_addresses_page_id и ms3_customer_orders_page_id равны нулю. MODX на нулевой идентификатор возвращает пустую ссылку и пишет ошибку в журнал.

Пока настройки не заполнены, в кабинете пустые ссылки «Войти» и «Зарегистрироваться». Выход ведёт в никуда, не работают переходы между разделами и ссылка на детали заказа.

Чем управляет ms3_customer_cancel_allowed_statuses

От неё зависит {$can_cancel} в строке заказа. В поставке стоит 2,3.

Очистка настройки отмену не запрещает: код подставит статусы из ms3_status_new и ms3_status_paid. Чтобы запретить отмену совсем, поставьте 0.

Обработка форм ​

Формы профиля и адресов отправляются POST-запросом, действие задаёт скрытое поле ms3_action:

ms3_actionДействие
customer/update-profileОбновление профиля
customer/address-createСоздание адреса
customer/address-updateОбновление адреса
html
<form method="post" data-ms3-form="customer">
    <input type="hidden" name="ms3_action" value="customer/update-profile">
    <div>
        <input type="text" name="first_name" value="{$customer.first_name}">
        <div class="invalid-feedback"></div>
    </div>
</form>

Две пометки, и обе обязательные

data-ms3-form="customer" (или класс ms3_customer_form) включает автосохранение: значение каждого поля уходит на сервер сразу после изменения. Без этой пометки форма молча ведёт себя как обычная HTML-форма — перезагружает страницу, и ничего не сохраняется.

Обёртка <div> вокруг поля тоже обязательна: обработчик ищет ближайший родительский div и без него прекращает работу, не дойдя до сохранения. В тот же div кладите .invalid-feedback — туда подставляется текст ошибки поля.

Действия без ms3_action ​

JS перехватывает клик по селектору:

СелекторДействие
.delete-addressУдаление адреса
.set-default-addressВыбор адреса по умолчанию
.ms3-order-cancelОтмена заказа
#resend-verification-emailПовторная отправка письма с подтверждением

Первые два стоят в штатном чанке строки адреса — tpl.msCustomer.address.row, файл ms3_customer_address_row.tpl.

Форма адреса: действие зависит от режима ​

Поле ms3_action одно, значение меняется по режиму — штатный чанк подставляет его сам:

fenom
<input type="hidden" name="ms3_action"
       value="customer/{if $mode == 'edit'}address-update{else}address-create{/if}">

Свой чанк должен делать то же: с address-create в режиме редактирования появится второй адрес вместо правки существующего.

CSS-классы ​

КлассЭлемент
.ms3-customer-accountКонтейнер личного кабинета
.ms3-customer-profileБлок профиля
.ms3-customer-ordersБлок заказов
.ms3-customer-addressesБлок адресов
.ms3-customer-order-detailsДетали заказа
.ms3_formФорма MiniShop3
.ms3_linkКнопка отправки формы