Данные страниц: что доступно шаблону
Переменные, которые есть на каждой странице, и то, что приходит своё на каждый раздел витрины.
На этой странице
- Есть на каждой странице
- $storefront
- $theme
- $action
- $seo
- $contacts
- $min_order
- $below_min, $free_shipping_left, $free_shipping_from
- $customer
- $errors, $status, $old
- $auth
- $cookies, $get, $request
- Постранично
- Страница оплаты заказа
- Набор листинга
- pagination
- filters
- active_filters
- Что приходит на отдельные страницы
- Блог
- blog и category
- Запись в ленте
- post — страница записи
- Заказы покупателя в кабинете
- Строка заказа
- Что добавляется на странице заказа
- items — состав заказа
- customer и recipient — поля заказа
- address — куда везти
- timeline — история заказа
- Текст страницы от владельца
- Как посмотреть данные своими глазами
Шаблон не ходит в базу данных — магазин отдаёт ему готовые данные. Часть из них есть на каждой странице, часть приходит своя на каждый раздел витрины.
Есть на каждой странице
| Переменная | Что внутри |
|---|---|
$storefront |
витрина: название, домен, язык, валюта, значок вкладки |
$theme |
значения настроек темы |
$action |
название текущего раздела |
$seo |
заголовок, описание и мета-теги для поисковика |
$shop |
помощник со списками магазина |
$contacts |
контакты магазина |
$customer |
покупатель или пусто, если он не вошёл |
$min_order |
наименьшая сумма заказа; 0 — без ограничения |
$below_min |
в корзине товары есть, но сумма ниже наименьшего заказа |
$free_shipping_left |
сколько добрать до бесплатной доставки; пусто — добирать не нужно |
$free_shipping_from |
с какой суммы доставка бесплатна; 0 — порога нет |
$errors |
ошибки формы после возврата назад |
$status |
сообщение об успехе |
$old |
введённые значения формы после возврата назад |
$auth |
как покупатель может войти: пароль, кнопки соцсетей, капча |
$cookies |
куки, которые поставил скрипт темы |
$get |
параметры адреса страницы |
$request |
то же, что $cookies и $get, записью вызова |
$storefront
{$storefront.name} название магазина
{$storefront.storefront_name} служебное имя витрины
{$storefront.domain}
{$storefront.locale} текущий язык: ru
{$storefront.locales} языки витрины
{$storefront.default_locale}
{$storefront.currency} валюта витрины: UAH
{$storefront.favicon}
name — это название магазина из общих настроек, его и показывают
покупателю. Служебное имя витрины лежит отдельно и нужно только магазинам с
несколькими витринами.
$theme
Значения настроек темы — плоско и по группам:
{$theme.copyright} {$theme.footer.copyright}
{$theme.per_page} {$theme.catalog.per_page}
{$theme.assets} /theme-assets/имя-темы
{$theme.colors.primary} {$theme.colors.accent}
{$theme.colors.bg} {$theme.colors.text}
Все поля схемы присутствуют, даже незаполненные — они приходят пустыми, и шаблон на них не падает. Подробности — на странице Файл theme.json.
$action
Название текущего раздела: default на главной, дальше category, product,
search, page, checkout/cart. Удобно для класса на <body> и для подсветки
активного пункта меню.
$seo
{$seo.title} {$seo.h1} {$seo.description}
{$seo.keywords} {$seo.robots} {$seo.indexable}
{$seo.canonical} {$seo.hreflang} {$seo.page_type}
{$seo.og.title} {$seo.og.description} {$seo.og.type}
{$seo.og.url} {$seo.og.image} {$seo.og.site_name}
{$seo.og.locale} {$seo.og.locale_alternates}
{$seo.twitter.card} {$seo.twitter.title} {$seo.twitter.description}
{$seo.twitter.image} {$seo.twitter.site}
Все ключи присутствуют всегда, поэтому {if $seo.og.image} безопасно. Магазин
считает эти значения сам, теме остаётся вывести их в <head> — готовый кусок
разметки есть на странице Каркас страницы.
$contacts
{if $contacts.phone}<a href="tel:{$contacts.phone_link}">{$contacts.phone}</a>{/if}
{$contacts.name} {$contacts.email} {$contacts.address}
phone_link — телефон, очищенный до цифр и +, готовый для href="tel:".
Незаполненное поле приходит пустой строкой, ключ на месте всегда.
Телефон из настроек темы превращается в ссылку модификатором |tel — он
оставляет только цифры и +:
<a href="tel:{$theme.phone_2|tel}">{$theme.phone_2}</a>
$min_order
Наименьшая сумма заказа из настроек оформления, в валюте витрины. Она есть на любой странице, поэтому её можно показать в шапке или в выезжающей корзине:
{if $min_order > 0}
<div class="cart-min" data-min-order="{$min_order}">
Минимальный заказ — {money amount=$min_order currency=$storefront.currency}
</div>
{/if}
Скриптам темы та же сумма приходит в window.CartiX.minOrder.
$below_min, $free_shipping_left, $free_shipping_from
Пороги корзины есть на любой странице, а не только в корзине: их показывают
в шапке, в выезжающей корзине, на странице товара. $below_min говорит, что
в корзине есть товары, но до наименьшего заказа не хватает. $free_shipping_left
— сколько осталось до бесплатной доставки (пусто, если порог пройден или его нет),
$free_shipping_from — сам порог.
Порог один для всех покупателей, а $below_min и $free_shipping_left — личные.
Страница каталога лежит в общем кеше витрины, и впечатать в неё чужую корзину
нельзя. Поэтому на такой странице $below_min ложно, а $free_shipping_left
пусто, и числа проставляет магазин в браузере. Разметьте блоки атрибутами —
остальное сделает /storefront/cart-sync.js, в том числе после каждого
изменения корзины:
<p data-cart-below-min{if !$below_min} hidden{/if}>
Минимальная сумма заказа: <b data-cart-min-order></b>
</p>
<p data-cart-free-row{if !$free_shipping_left} hidden{/if}>
До бесплатной доставки осталось <b data-cart-free-left></b>
</p>
Страница, которая в общий кеш не попадает (покупатель вошёл, корзина, оформление), получает числа сразу, и блок виден без задержки.
$customer
Для гостя — пусто, поэтому {if $customer} достаточно.
{$customer.id} {$customer.name} {$customer.initial}
{$customer.first_name} {$customer.last_name} {$customer.middle_name}
{$customer.company} {$customer.email} {$customer.phone}
{$customer.member_since}
$errors, $status, $old
После формы, отправленной обычным POST и вернувшейся с ошибкой:
{if $status}<p class="ok">{$status}</p>{/if}
<input name="email" value="{$old.email|default:''}">
{if $errors.email}<span class="err">{$errors.email}</span>{/if}
Ошибок нет — $errors пустой список. Подробности — на странице
Формы витрины.
$auth
Способы входа, которые владелец включил в «Регистрации и входе» витрины. Есть на каждой странице — поэтому окно входа можно поставить прямо в шапку.
{$auth.password} вход по паролю включён
{$auth.registration} регистрация открыта
{$auth.login_by} phone — по телефону, both — по телефону или почте
{$auth.subscribe} предлагать подписку при регистрации
{foreach $auth.socials as $s}
<a href="{$s.url}">{$s.title}</a> {$s.code}: google, facebook, telegram
{/foreach}
{$auth.captcha.required} {$auth.captcha.provider} {$auth.captcha.site_key}
Форма входа уходит на /account/login (поля identifier, password,
remember). Добавьте поле return с адресом текущей страницы — после входа
покупатель останется на ней, а не уйдёт в кабинет. То же для кнопок
соцсетей: {$s.url}?return=/адрес. Принимается только адрес своего сайта.
$cookies, $get, $request
Куки и параметры адреса — для решений, которые должен принять сервер. Пример: закрытый покупателем баннер не выводится вовсе, а не прячется скриптом после загрузки.
{if $cookies.cx_promo_closed != 'header-promo'} …баннер… {/if}
{$get.page} ?page=2 → 2
{$request->cookie('cx_view')} {$request->get('sort')} {$request->path()}
Шаблону видны только куки, которые поставил скрипт в браузере
(document.cookie). Куки магазина — сессия, корзина, чат — не видны. Кука,
которой нет, читается пустой строкой. В $get только простые значения: из
адреса ?page[]=1 параметр page придёт пустым.
Страница с прочитанной кукой хранится в общем кеше отдельной копией на каждое её значение — магазин запоминает, какие куки читают шаблоны. Поэтому читайте только куки выбора покупателя (закрыл баннер, выбрал вид каталога), а не уникальные (идентификаторы аналитики): иначе кеш превратится в копию страницы на каждого посетителя. Больше двадцати разных имён магазин не запоминает — такие куки читаются пустыми.
{$smarty.cookies} и {$smarty.get} в шаблонах закрыты: в Smarty они
открываются вместе с {$smarty.server}, а там служебные пароли сайта.
Постранично
Данные страницы кладутся поверх общих и могут перекрыть любую из них — не
называйте свои переменные product, если на странице уже есть товар.
| Страница | Шаблон | Переменные |
|---|---|---|
| Главная | home.html |
только общие: содержимое собирается через $shop |
| Категория | category.html |
category, breadcrumbs, landing + набор листинга |
| Товар | product.html |
product, breadcrumbs, rec_cross, rec_up, reviews, questions |
| Страница владельца | page.html |
page, breadcrumbs |
| Поиск | search.html |
query, category_id, has_query, corrected + набор листинга |
| Бренд | brand.html |
brand, breadcrumbs + набор листинга |
| Все бренды | brands.html |
brands |
| Метка | tag.html |
tag, breadcrumbs + набор листинга |
| Все метки | tags.html |
tags |
| Подборка | product-list.html |
list, breadcrumbs + набор листинга |
| Лента блога | blog.html |
blog, categories, posts, pagination, total, breadcrumbs |
| Рубрика блога | blog-category.html |
blog, category, categories, posts, pagination, total, breadcrumbs |
| Запись блога | blog-post.html |
blog, post, products, related, breadcrumbs |
| Метка блога | blog-tag.html |
blog, tag, categories, posts, pagination, total, breadcrumbs |
| Корзина | checkout/cart.html |
items, cart, min_order, below_min, free_shipping_left |
| Оформление | checkout/layout.html |
checkout |
| Заказ принят | checkout/success.html |
order, is_authenticated |
| Оплата заказа | checkout/pay.html |
order, order_id, is_paid, is_online, show_offline_note |
| Ошибка оплаты | checkout/pay-error.html |
order_id |
| Избранное | favorites.html |
products |
| Сравнение | compare.html |
колонки товаров и строки характеристик |
| Вход | account/login.html |
auth, captcha |
| Регистрация | account/register.html |
auth, captcha, reg_types |
| Обзор кабинета | account/dashboard.html |
orders, orders_count, bonus |
| Заказы | account/orders.html |
orders, pagination, filters |
| Один заказ | account/order.html |
order |
| Профиль | account/profile.html |
profile |
| Не найдено | 404.html |
только общие |
| Магазин закрыт | maintenance.html |
message |
Страница оплаты заказа
Покупатель попадает сюда из кабинета и по ссылке из письма или SMS.
| Переменная | Что внутри |
|---|---|
is_paid |
заказ уже оплачен — предлагать оплату нечего |
is_online |
способ уводит на страницу банка: показываем кнопку «Оплатить» |
show_offline_note |
показывать ли подпись «этот заказ оплачивается при получении» |
Подпись нужна не всегда. Оплата по счёту тоже никуда не уводит, но показывает
на этой же странице кнопку со счётом — и подпись про оплату курьеру прямо ей
противоречит. Поэтому вместо {else} пишется {elseif $show_offline_note}:
{if $is_online}
<button type="button" data-pay-submit>{trans key="storefront.pay_now"}</button>
{elseif $show_offline_note}
<p>{trans key="storefront.pay_offline"}</p>
{/if}
Тема, написанная раньше и не знающая про эту переменную, работает по-прежнему: подпись в ней остаётся у всех способов без страницы банка.
Набор листинга
Одинаков у категории, поиска, бренда, метки и подборки — поэтому список товаров, фильтры и постраничная навигация пишутся один раз и включаются во все эти страницы.
| Переменная | Что внутри |
|---|---|
products |
карточки товаров текущей страницы |
pagination |
постраничная навигация |
total |
сколько товаров нашлось всего |
filters |
доступные фильтры |
active_filters |
чипсы выбранных условий, у каждого адрес «снять» |
filter_chips |
показывать ли чипсы |
selected |
что выбрано сейчас |
sort, sort_options |
текущая сортировка и её варианты |
action_url |
адрес, на который отправляется форма фильтра |
reset_url |
адрес «сбросить всё» |
keep_params |
параметры, которые нужно сохранить при переходе |
has_filters, show_filters |
есть ли фильтры и показывать ли панель |
lazy_load |
подгружать товары кнопкой «Показать ещё» |
filter_mode |
ajax — применять сразу, button — по кнопке |
filter_show_counts |
показывать счётчики у значений фильтра |
image_lazy |
подгружать картинки при прокрутке |
pagination
{if $pagination.has_pages}
{if $pagination.prev_url}<a href="{$pagination.prev_url}">Назад</a>{/if}
{foreach $pagination.pages as $p}
{if $p.ellipsis}<span>…</span>
{else}<a href="{$p.url}"{if $p.active} class="is-active"{/if}>{$p.num}</a>{/if}
{/foreach}
{if $pagination.next_url}<a href="{$pagination.next_url}">Вперёд</a>{/if}
{/if}
Ещё есть current, last, from, to, total — для подписи «Показано 1–24
из 137».
filters
| Ключ | Что внутри |
|---|---|
all |
вся колонка одним списком, по порядку — рисуйте фильтры по нему |
price |
min, max, from, to, active |
in_stock |
count, selected, disabled — либо пусто, если фильтр выключен |
discount |
то же |
warehouses |
фильтр по складам |
features |
словарные характеристики: цвет, материал, бренд |
ranges |
размерные характеристики: длина, вес, мощность |
booleans |
характеристики «да/нет» |
Рисуйте фильтры списком по данным, а не по именам. Набор характеристик у каждого магазина свой: хардкод «цвет, размер, бренд» на чужом магазине покажет пустоту.
filters.all — колонка по порядку (с ядра 2.59.0)
Состав и порядок колонки задаёт владелец в настройках раздела: какие фильтры в
нём стоят, нужны ли цена, наличие, скидка и склад, что идёт первым. Готовый
порядок приходит в filters.all — рисуйте колонку по нему, иначе расстановка
владельца до покупателя не дойдёт.
У каждой строки три поля: kind — что это за фильтр, id — номер
характеристики (у цены, наличия, скидки и склада его нет), data — то же
самое, что лежит в ключах выше.
kind |
Что в data |
|---|---|
price |
то же, что в filters.price |
in_stock, discount |
то же, что в одноимённом ключе |
warehouse |
список складов, как в filters.warehouses |
feature |
характеристика со списком значений |
range |
числовая характеристика (ползунок «от–до») |
boolean |
характеристика «да/нет» |
{foreach $filters.all as $block}
{if $block.kind == 'feature'}
<div class="filter-group">
<div class="filter-group__title">{$block.data.name}</div>
{foreach $block.data.values as $v}
<label>
<input type="checkbox" name="f[{$block.data.id}][]" value="{$v.id}"
{if $v.selected}checked{/if} {if $v.disabled}disabled{/if}>
{$v.label}
</label>
{/foreach}
</div>
{elseif $block.kind == 'price'}
…
{/if}
{/foreach}
Отдельные ключи (features, ranges, booleans, price и прочие) остались на
месте: тема, написанная до 2.59.0, работает по-прежнему. С ядра 2.107.0 они тоже
слушают настройки раздела: внутри каждого ключа фильтры идут в порядке
владельца, а in_stock, discount и warehouses пусты, если владелец убрал их
из раздела. price приходит всегда: старые темы рисуют цену без проверки. Но
каждый вид такая тема рисует своей пачкой, поэтому ползунок «от–до» в ней
оказывается под всеми списками, куда бы владелец его ни поставил. Порядок
целиком соблюдает только filters.all.
Значение, по которому при текущем выборе товаров нет, приходит с признаком
disabled — его показывают приглушённым, а не прячут: иначе покупатель не
понимает, куда делся вариант.
active_filters
Чипсы выбранных условий. У каждого свой адрес без этого условия, поэтому снятие фильтра работает и без скриптов:
{foreach $active_filters as $chip}
<a href="{$chip.url}" class="chip">{$chip.label} ✕</a>
{/foreach}
Что приходит на отдельные страницы
Категория всегда получает landing, даже на обычной категории — там это
пустые text_top, text_bottom и related. Сделано, чтобы шаблон писался один
раз, без проверки «а есть ли посадочная страница».
Поиск при запросе короче двух букв получает только query, category_id,
has_query (пусто) и total (ноль) — ни листинга, ни фильтров. Отдельная ветка
«введите хотя бы два символа» в шаблоне нужна.
Корзина: items — позиции, cart — итоги, min_order и below_min —
минимальная сумма заказа, free_shipping_left — сколько добрать до бесплатной
доставки (пусто, если добирать не нужно или порога нет).
Оформление получает checkout. У пустой корзины там только признак «пусто»
и сама корзина; иначе — settings (какие поля включены), prefill,
contact_types, recipient_fields, recipient_company_fields,
saved_addresses, location_fields, cart, calc и то, что добавили
дополнения.
Подборка — страница, которую владелец включает у подборки товаров
переключателем «Сделать отдельную страницу». Кроме набора листинга она получает
list:
| Поле | Что внутри |
|---|---|
name |
название подборки |
description |
текст подборки, готовый HTML — выводится с nofilter |
slug |
адрес подборки |
url |
путь страницы: /list/адрес/ с языковым префиксом витрины |
categories |
категории, выбранные в правилах подборки (источник «На категории»), с подкатегориями, если отмечено «с подкатегориями»; у подборки другого вида — пусто |
product_categories |
категории, в которых лежат товары подборки: основная категория товара и те, к которым он привязан |
Оба списка — в порядке дерева каталога, только включённые категории этой витрины.
У каждой категории: id, parent_id, name, url, level (0 — верхний уровень,
1 — подкатегория и так далее) и count — сколько товаров подборки в ней вместе
с подкатегориями. С ядра 2.54.0.
{if $list.categories}
<nav class="list-cats">
{foreach $list.categories as $cat}
<a href="{$cat.url}" style="margin-left: {$cat.level * 16}px">{$cat.name} ({$cat.count})</a>
{/foreach}
</nav>
{/if}
Шаблон почти совпадает с tag.html: тот же листинг, другой заголовок. Если в
вашей теме product-list.html нет, магазин возьмёт его из стандартной темы —
см. Из чего состоит тема.
<h1>{$list.name}</h1>
{if $list.description}<div class="cms-body">{$list.description nofilter}</div>{/if}
{foreach $products as $product}
{include file="partials/product-card.html" product=$product}
{/foreach}
{include file="partials/pagination.html" pagination=$pagination}
Отзывы могут прийти одним ключом: если владелец выключил отзывы, в
$reviews будет только признак «выключено». Обращаться к $reviews.items без
проверки нельзя.
Блог
Четыре страницы блога получают одинаковые куски: blog — сам блог, posts —
записи текущей страницы, categories — рубрики верхнего уровня для меню блога.
blog и category
| Поле | Что внутри |
|---|---|
id, slug |
номер и адрес |
name |
название |
summary |
короткое описание для ленты и поисковиков |
description |
текст, готовый HTML — выводится с nofilter; в меню и карточках только с full |
url |
путь страницы |
cover, cover_thumb, banner |
обложка, её эскиз и широкий баннер; пусто, если не загружены |
icon |
значок блога (только у blog) |
parent_id |
номер родительской рубрики; пусто у верхнего уровня (только у рубрики) |
children |
вложенные рубрики с теми же полями (только у рубрики) |
parent |
родительская рубрика с теми же полями, без children (только у category) |
Каждый элемент categories — рубрика со всеми полями из этой таблицы, включая
children. Поэтому меню блога можно рисовать с обложками, баннерами и
раскрывающимися ветками. Выключенные рубрики и всё, что под ними, в меню не
попадают.
Полное описание description собирается из текстового редактора вместе со всеми
вставками, и у рубрики с подборкой статей это заметная работа. Поэтому сам блог
и открытая рубрика получают его всегда, а в меню, в карточках записей и в списке
блогов оно пустое, пока тема не попросит полные данные параметром full:
$shop->blogCategories($blog.id, true) — меню рубрик с описаниями,
$shop->blogs(true) — блоги с описаниями, {posts full=true} и
$shop->posts(['full' => true]) — записи, у рубрик которых есть описание.
У родителя и вложенных рубрик открытой рубрики (parent, children) и у рубрики
записи на её странице (post.category) описания тоже нет — его берут из
$shop->blogCategories($blog.id, true). Остальные поля приходят всегда. На странице метки вместо рубрики приходит tag с полями id,
slug, name и url.
Запись в ленте
Так выглядит каждый элемент posts и related, и именно это получает
partials/blog-card.html:
| Поле | Что внутри |
|---|---|
id, slug |
номер и адрес |
title |
заголовок |
summary |
анонс |
url |
путь записи |
cover, cover_thumb |
обложка целиком и её эскиз для карточки |
banner |
широкий баннер записи |
author |
автор |
reading_time |
минут на чтение |
views |
сколько раз прочитали |
is_pinned |
запись закреплена вверху ленты |
date, date_label, date_iso |
дата: 2026-09-17, «17 сентября 2026» на языке витрины, полная для <time datetime> |
category |
главная рубрика со всеми полями рубрики, кроме children и parent; пусто, если рубрика выключена |
categories |
все рубрики записи с теми же полями; выключенных среди них нет |
tags |
метки записи: id, slug, name и url |
{foreach $posts as $post}
{include file="partials/blog-card.html" post=$post}
{/foreach}
{include file="partials/pagination.html" pagination=$pagination}
Такую же запись отдаёт тег {posts} — им статьи ставят на главную и в любое
другое место темы. Условия подборки и примеры — на странице
Теги магазина.
post — страница записи
Всё, что есть у записи в ленте, и ещё:
| Поле | Что внутри |
|---|---|
content |
текст статьи, готовый HTML — выводится с nofilter |
anchors |
оглавление по заголовкам статьи: у каждого id и name |
Рядом со статьёй приходят products — товары, которые владелец привязал к
записи (карточки как в каталоге; пусто, если блок выключен в настройках блога),
и related — записи для блока «читайте также».
<article data-blog-post="{$post.id}">
<h1>{$post.title}</h1>
{if $post.anchors}
<ol>{foreach $post.anchors as $a}<li><a href="#{$a.id}">{$a.name}</a></li>{/foreach}</ol>
{/if}
<div class="cms-body">{$post.content nofilter}</div>
</article>
Атрибут data-blog-post обязателен: по нему магазин считает прочтения. Сам
скрипт счётчика подключает магазин, в теме его писать не нужно.
Заказы покупателя в кабинете
Список заказов (account/orders.html) получает orders — строки заказов,
pagination — страницы и filters — из чего покупателю выбирать в отборе
(shipping, payment, statuses и current — что выбрано сейчас). Список
перерисовывается на месте, поэтому саму таблицу выносят в
account/partials/orders-table.html: магазин просит у темы этот же кусок
разметки и подставляет его обратно.
Страница одного заказа (account/order.html) получает order. Заказ —
снимок: суммы, названия способов и данные покупателя останутся такими, какими
были в день покупки, даже если магазин потом всё это переименует.
Строка заказа
Эти поля есть и у строки списка, и у карточки — вёрстку можно писать один раз.
| Поле | Что внутри |
|---|---|
number |
номер, каким его видит покупатель (с оформлением из настроек) |
number_raw |
номер для адреса страницы: в оформлении бывает #, и ссылка сломалась бы |
date |
дата оформления |
status, status_label, status_color |
код статуса, его название и цвет |
total, currency |
сумма и валюта заказа |
items_count |
сколько позиций |
shipping_name, shipping_logo |
способ доставки и его логотип |
payment_name, payment_logo |
способ оплаты и его логотип |
payment_status, payment_status_label |
состояние оплаты и его название |
is_paid |
оплачен ли заказ полностью |
paid_total, due |
сколько внесено и сколько осталось заплатить |
pay_url |
адрес страницы оплаты — либо пусто |
comment |
комментарий покупателя |
tracking |
номер накладной перевозчика |
Логотип приходит пустым, если владелец его не загружал или способ уже удалён — тогда остаётся название, снятое с заказа при оформлении:
{if $order.shipping_logo}<img src="{$order.shipping_logo}" alt="">{/if}
{$order.shipping_name|default:'—'}
pay_url есть только у неоплаченного заказа и только у способа, который уводит
на страницу банка. У оплаты при получении и оплаты по счёту его нет и быть не
должно — кнопка вела бы в никуда:
{if $order.pay_url && $order.due > 0}
<a href="{$order.pay_url}">Оплатить {money amount=$order.due currency=$order.currency}</a>
{/if}
Что добавляется на странице заказа
| Поле | Что внутри |
|---|---|
placed_at, paid_at |
когда заказ оформлен и когда оплачен, со временем |
items_total, services_total, discount_total |
товары, услуги, скидка |
shipping_total, tax_total, bonus_total |
доставка, налог, оплата баллами |
extra_total |
всё, что дополнение добавило к итогу сверх этих строк |
discounts |
какие правила сработали и на сколько |
promo_code |
промокод, если покупатель его вводил |
needs_callback |
покупатель просил перезвонить |
items |
состав заказа |
customer |
что покупатель указал о себе |
recipient |
другой получатель — либо пусто |
address |
адрес доставки |
timeline |
история смен статуса |
Строки обязаны складываться в итог. extra_total для того и есть: в сумму
заказа мог войти пункт, которого в остальных строках нет — например надбавка за
способ оплаты от дополнения. Покажите его отдельной строкой, иначе покупатель
сложит столбиком и получит не ту сумму.
items — состав заказа
| Поле | Что внутри |
|---|---|
name, sku_code |
название и артикул на день покупки |
image |
фотография варианта — либо пусто |
url |
ссылка на товар; пусто, если товара в каталоге больше нет |
qty, unit |
количество и единица продажи |
pack |
packs и rest, если товар брали упаковками |
price, compare_price |
цена и старая цена |
discount_total, total |
скидка на позицию и её сумма |
services |
услуги к этой позиции: name, price, total |
Фотографии может не быть — товар сняли с продажи или её вовсе не загружали. Ставьте на это место значок, пустая рамка читается как сломанная картинка.
customer и recipient — поля заказа
Оба приходят списком: code, name, value. Названия — те же, которыми поля
названы у магазина в разделе «Оформление заказа», поэтому рисуйте их циклом, а
не по именам: набор полей у каждого магазина свой, и заказ компании несёт ещё
название и налоговый номер.
{foreach $order.customer as $field}
<p><span>{$field.name|escape}</span> <span>{$field.value|escape}</span></p>
{/foreach}
recipient приходит пустым, если заказ оформляли на себя.
address — куда везти
name, phone, email, country, region, city, zip, street (улица,
дом и квартира одной строкой), отдельно street_name, building, apartment,
а также point и point_number — выбранное отделение или пункт выдачи. При
доставке в отделение улицы нет и не будет: магазин намеренно её не заполняет,
чтобы в документах не оказалось и адреса, и отделения сразу.
timeline — история заказа
Смены статуса по порядку: date, status, status_label и comment
менеджера. Внутренних пометок сотрудников покупателю не показывают — их в этом
списке нет.
Текст страницы от владельца
Текст, который владелец пишет внизу главной ради поиска, лежит не в теме, а в разделе «SEO → SEO-оптимизация» — свой для каждой витрины и каждого языка. Тема печатает его одной строкой:
{seo_text}
Тег печатает текст той страницы, которая открыта (на главной — её текст).
Нужен текст другой страницы — {seo_text page="home"}. Нужна своя вёрстка
блока — положите текст в переменную и рисуйте сами:
{seo_text assign='seo_page_text'}
{if $seo_page_text|default:'' !== ''}
<section class="seo-text">{$seo_page_text nofilter}</section>
{/if}
Текста нет — тег не печатает ничего: пустого блока на странице быть не должно. Дополнение «SEO-оптимизация» может быть не установлено — тогда тег тоже молчит, и тема работает как прежде. С ядра 2.58.0.
Как посмотреть данные своими глазами
{dump} что вообще доступно этому шаблону
{dump var=$product} одно значение целиком
{dumpc var=$product} то же в консоль браузера
Видит только сотрудник магазина — покупателю блок не покажется. Это самый быстрый способ понять, что приходит на конкретную страницу, и он всегда актуальнее любой таблицы.