Перейти к содержимому

Что доступно в контексте

Контекст шаблона в PageCraft маленький и закрытый: в нём ровно то, что перечислено на этой странице. Обращение к чему-то ещё не вызывает ошибки — оно просто выводит пустую строку, поэтому опечатка выглядит как «блок отрендерился, но текста нет».

Переменная Когда есть Что внутри
props.* всегда значения полей схемы блока
content только у markdown-блоков HTML, полученный из markdown-редактора
data.* только у блоков со слотами данных живые данные витрины

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

Каждое поле схемы блока становится ключом внутри props, вложенность повторяет схему:

{{ props.title }} {# поле text #}
{{ props.button.label }} {# поле object #}
{% for item in props.items %} {# поле array #}
{{ item.title }}{{ item.url }} {# внутри цикла — без props #}
{% endfor %}
{% if props.is_wide %}wide{% endif %} {# поле switch: true/false #}

Что попадает в значения — зависит от типа поля: switch даёт true/false, select и radio — строку value варианта, image — URL файла, остальные типы — строку. Полный разбор типов — Схема полей.

У блока с типом «markdown» текст из WYSIWYG-редактора конвертируется в HTML и кладётся в корневую переменную contentбез префикса props:

<article class="post" style="max-width: {{ props.max_width | default: '800px' }}">
{{ content }}
</article>

Вставлять как есть: там уже готовый HTML, экранировать его не нужно. Остальные поля схемы у такого блока живут в props обычным образом. Подробности — Markdown в блоках.

Если блок объявил в схеме bindingSlots, каждый слот доступен в шаблоне по своему имени внутри data:

{% for product in data.products.items %}
<a class="card" href="{{ product.url }}">
<img src="{{ product.image }}" alt="{{ product.name }}" loading="lazy">
<span>{{ product.name }}</span>
<b>{{ product.price }}</b>
</a>
{% endfor %}
<p>Всего: {{ data.products.total }}</p>

Форма данных описана типом результата слота, а не вами: product_list всегда устроен одинаково, откуда бы товары ни пришли.

У макета контекст другой — он знает о странице и сайте:

Переменная Что внутри
content HTML всех блоков страницы по порядку
blocks_css CSS всех блоков страницы, склеенный
blocks_js JS всех блоков страницы, склеенный
page.id числовой идентификатор страницы
page.slug адрес страницы
page.title название страницы
page.meta_title SEO-заголовок
page.meta_description SEO-описание
settings.* значения настроек макета для этого сайта
site.name название сайта
site.variables.* переменные сайта
<!doctype html>
<html lang="ru">
<head>
<title>{{ page.meta_title | default: page.title }}</title>
<meta name="description" content="{{ page.meta_description }}">
<style>{{ blocks_css }}</style>
</head>
<body>
<header>{{ settings.header_title | default: site.name }}</header>
{{ content }}
<script>{{ blocks_js }}</script>
</body>
</html>

props в макете нет — это переменная блока. И наоборот: page, settings и site недоступны в шаблоне блока.

Переменные сайта — отдельный механизм, к Liquid отношения не имеющий. Пишете @имя где угодно в шаблоне, а подстановка выполняется после рендеринга, простой заменой по тексту:

<a href="mailto:@support_email">Написать нам</a>
<p>© @brand_name</p>

Работает и в блоке, и в макете, но не заменяет props: переменная сайта одна на весь сайт, а поле блока задаётся на каждой странице.

Хочу вывести Пишу
Значение поля блока {{ props.field }}
Поле внутри повторяющейся группы {% for i in props.items %}{{ i.field }}{% endfor %}
Текст markdown-блока {{ content }}
Данные из слота {{ data.slot_name… }}
Заголовок страницы (в макете) {{ page.title }}
Общий телефон компании @phone — переменная сайта

Источники: backend/src/Publishing/BlockRenderer.php (buildContext, buildDefaultData, applyVariables), backend/src/Publishing/LayoutRenderer.php (render), backend/src/Publishing/BlockAssembler.php, backend/src/Publishing/Provider/FourCmsProvider.php (buildSsrContext), front/src/lib/placeholder.ts, front/src/components/PageEditor/PageEditor.tsx, backend/public/block-schema.json.