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

Переменные сайта

Переменные сайта — плоский словарь «имя → значение», который хранится у сайта и подставляется в готовый HTML при рендере страницы. Это способ не вписывать название магазина, телефон и адрес поддержки в каждый блок руками.

В интерфейсе: сайт → Переменные сайта. Строка = имя + значение, переменных может быть сколько угодно.

Имя обязано подходить под шаблон ^[a-zA-Z][a-zA-Z0-9_]*$: латинская буква в начале, дальше латиница, цифры и подчёркивание. Кириллица, дефис, точка и пробел не допускаются — форма подсветит ошибку, а бэкенд молча выбросит такую пару при сохранении.

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

Через API переменные — часть настроек сайта, отдельного эндпоинта у них нет:

PUT /api/sites/{id}
Content-Type: application/json
{ "variables": { "shop_name": "Магазин", "phone": "+7 900 000-00-00" } }

Поле variables заменяет словарь целиком, а не дополняет его: чтобы удалить переменную, отправьте объект без неё. {} очищает все переменные, отсутствие поля — не меняет ничего.

В любом тексте пишете @имя:

<footer>
{{ props.title }} — @shop_name, телефон @phone
</footer>

Работает и в шаблоне блока, и в значениях полей блока, и в шаблоне макета — подстановка идёт по итоговому HTML, поэтому объявлять переменную в схеме блока не нужно, и в контекст Liquid она не попадает.

Порядок такой:

  1. Liquid рендерит шаблон блока → HTML.
  2. По этому HTML прогоняется замена @имя → значение.
  3. Шаблон макета рендерится Liquid и оборачивает блоки.
  4. По итоговому HTML макета замена @имя прогоняется ещё раз.

Внутри Liquid-шаблона макета переменные дополнительно доступны как {{ site.variables.имя }}, рядом с {{ site.name }}. В шаблоне блока такого доступа нет — только @имя.

Замена — это регулярное выражение по всему HTML, а не аккуратная подстановка известных имён. Правило одно и жёсткое:

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

Что из этого ломается на практике:

В шаблоне Что получится
info@example.com info.com@example съеден
@media (max-width: 600px) в CSS макета или блока (max-width: 600px) — правило разваливается
@keyframes, @font-face, @import то же самое
@click, @input (синтаксис Vue/Alpine) атрибут теряет имя

CSS блока попадает под замену не всегда: он проходит через неё, когда страница собирается с макетом (макет вставляет CSS блоков в свой шаблон, а замена идёт по результату). Если сайт публикуется без макета, CSS уезжает провайдеру отдельным полем и остаётся нетронутым. Полагаться на это не стоит — макет может появиться позже.

Как жить:

  • пока у сайта нет ни одной переменной, замена не выполняется вовсе;
  • нужны медиазапросы и почта в тексте — не заводите переменные на этом сайте либо выносите такой CSS/текст туда, где @ не встречается;
  • почту собирайте из частей: {{ props.user }}&#64;{{ props.domain }} или через HTML-сущность &#64;.

Редактор страницы подставляет переменные тем же способом, что и сервер, — предпросмотр показывает реальные значения. В редакторе блока переменные не подставляются: там блок рендерится вне контекста сайта, и @имя останется текстом.

  • Неизвестное имя → пустая строка, без сообщения в логе и без пометки в HTML.
  • Значение подставляется как есть, без экранирования: HTML внутри значения попадёт в страницу разметкой.
  • Переменные не участвуют в условиях Liquid внутри блока — на момент рендера шаблона их ещё нет.
  • backend/src/Entity/Site.php — поле variables
  • backend/src/Service/Site/UpdateSiteService.php — валидация имён, полная замена словаря
  • backend/src/Publishing/BlockRenderer.phpapplyVariables()
  • backend/src/Publishing/LayoutRenderer.php — контекст site.variables, повторная замена
  • backend/src/Publishing/Provider/FourCmsProvider.php — что уходит провайдеру с макетом и без
  • front/src/lib/placeholder.ts, front/src/components/SiteVariablesModal.tsx — предпросмотр и форма