Шаблон задаёт вид страницы, чанк хранит повторяющийся кусок разметки. Остались вещи, которые нельзя ни нарисовать заранее, ни скопировать: меню, которое само знает обо всех разделах, и картинка-анонс, которой у страницы по умолчанию нет. Этим занимаются сниппеты и TV-поля.
Сниппет — кусок программы
Сниппет (snippet, «фрагмент») — небольшая программа на PHP, которая запускается в момент сборки страницы и возвращает готовый HTML. Вызывается так же коротко, как чанк, только скобки другие — квадратные:
<nav class="main-nav">
[[DocLister? &parents=`3` &tpl=`menu-item`]]
</nav>
Что здесь происходит: движок дошёл до этой строки, запустил
сниппет DocLister, передал ему два параметра —
откуда брать страницы и каким чанком рисовать каждую.
Сниппет сходил в базу, собрал детей третьего раздела, обернул
каждого в разметку чанка и вернул готовый кусок HTML. На странице этот
вызов не виден вообще — вместо него стоит результат.
Разница с чанком ровно в одном слове. Чанк подставляется, сниппет выполняется. Чанк вернёт то же самое на любой странице; сниппет каждый раз считает заново и на разных страницах вернёт разное.
Писать свои сниппеты не придётся
Хорошая новость для человека, который не знает PHP: девять задач из десяти закрываются готовыми сниппетами. Они ставятся из админки, а от вас требуется только правильно их вызвать.
| Сниппет | Что делает | Где на этом сайте |
|---|---|---|
| DocLister | Выводит список страниц по дереву: меню, каталог, лента материалов | Мегаменю, боковое меню этапа, маршрут, подвал |
| DLCrumbs | Считает путь от главной до текущей страницы | Крошки на каждой внутренней странице |
| DLPrevNext | Находит соседей страницы в дереве | Кнопки «Назад» и «Дальше» внизу страницы |
| ElForm | Проверяет форму и отправляет письмо. Свой: готового в поставке нет | Форма обратной связи |
Каждый из них настраивается параметрами — теми самыми
&имя=`значение` после знака вопроса. Их
бывает много, но выучивать нечего: список параметров лежит
в документации сниппета, а нужны обычно три-четыре.
Разметку задаёте вы, а не сниппет
У DocLister и его родни есть параметры вроде
&tpl — в них передают имя чанка, по
которому рисовать каждый пункт. Значит, сниппет отвечает
только за то, какие страницы вывести, а
как они выглядят, решает ваш чанк. Вёрстка
остаётся вашей — ради этого и выбиралась Evolution.
Другие скобки и кэш
Evolution запоминает собранные страницы, чтобы не пересобирать их на каждое открытие. Обычно это хорошо: меню меняется редко, и считать его сто раз незачем.
Но есть вещи, которые обязаны быть свежими всегда: результат
поиска, форма, вывод случайной цитаты. Такой вызов пишут
в других скобках — вместо
[[Сниппет]]. Это и значит «не бери из памяти,
посчитай сейчас».
[[DocLister? &parents=`3`]] <!-- меню: можно из кэша -->
<!-- свежий список: заново -->
<!-- форма: всегда заново -->
Самая частая потеря времени новичка
Правите форму, обновляете страницу — ничего не меняется. Кажется, что код не работает. На самом деле браузеру отдали сохранённую копию. Два лекарства: другие скобки там, где нужна свежесть, и кнопка очистки кэша в админке. Прежде чем искать ошибку в коде, очистите кэш.
Вторая ловушка — запись [[!Сниппет]],
привычная по другим движкам. Evolution читает её как имя
сниппета «!Сниппет»: не находит и выводит пустое место.
Без ошибки и без следа в журнале.
TV-поле — своё поле у страницы
У каждой страницы есть готовый набор полей: заголовок, текст, описание. Их хватает ровно до первой задачи из жизни. Например, карточке мануала на хабе нужны картинка и время чтения. Куда их положить? В текст нельзя — он идёт в статью целиком.
Для этого и придуманы TV-поля (template variables, «переменные шаблона»). Вы создаёте новое поле в админке, привязываете его к нужным шаблонам — и в форме редактирования страницы появляется ещё одно поле для заполнения.
Вызывается TV-поле так же, как встроенное, — по имени в скобках со звёздочками. Отличить его от родного поля по коду нельзя, и это удобно:
<article class="card">
<img src="[*cover*]" alt="" width="640" height="360" loading="lazy">
<h3 class="card__title">[*pagetitle*]</h3>
<p class="card__text">[*introtext*]</p>
<span class="chip">[*reading_time*] мин</span>
</article>
Здесь [*pagetitle*] и [*introtext*] —
встроенные поля, а [*cover*] и
[*reading_time*] — придуманные мной TV.
В админке они выглядят как обычные поля формы: у первого —
кнопка выбора файла, у второго — строка ввода.
У TV есть тип
Тип решает, как поле выглядит в админке и что в него можно положить. Правильно выбранный тип избавляет от ошибок: человек, который заполняет страницу, просто не сможет вписать чушь.
| Тип | Как выглядит в админке | Для чего |
|---|---|---|
| Текст | Однострочное поле | Время чтения, подпись, короткий слоган |
| Изображение | Кнопка выбора файла из менеджера | Обложка материала, картинка для Open Graph |
| Список | Выпадающий список с готовыми значениями | Уровень сложности: новичок, средний, продвинутый |
| Флажок | Галочка | «Показывать на главной», «Материал готов» |
| Дата | Календарь | Дата публикации, если нужна своя |
Как это выглядит в админке
-
Сниппеты: свои и чужие в одном списке
Закладка «Сниппеты». Сверху — семейство DocLister, поставленное из каталога расширений, ниже — четыре своих. Имя из этого списка и пишут в квадратных скобках.
-
TV-поля заводятся один раз на сайт
Закладка «Параметры (TV)». Каждая строка — новое поле в карточке страницы. У этого сайта их шесть: тексты для мессенджера, три строки условий мануала и обстановка вокруг статьи.
-
Заполняются они в карточке страницы
Заведённое поле появляется у страницы отдельным блоком «Параметры (TV)» — с тем названием и пояснением, которые вы ему дали. Под названием видно имя, которым поле зовут в шаблоне.
Четыре понятия рядом
Теперь можно собрать всё вместе. Эта таблица — короткий ответ на вопрос «что из них что», ради которого и затевался этап.
| Понятие | Что это | Как вызвать |
|---|---|---|
| Шаблон | Вёрстка страницы целиком, с метками вместо текста | Выбирается у страницы в админке |
| Чанк | Повторяющийся кусок разметки | {{header}} |
| Сниппет | Программа: считает и возвращает готовый HTML | [[DocLister]] |
| TV-поле | Своё поле страницы сверх встроенных | [*cover*] |
Что я спросил у нейросети
Первый же вызов DocLister выдал у меня не то меню, которое я ждал: в списке разделов оказались внутренние страницы. Разбираться в параметрах по документации долго, поэтому я описал задачу словами.
Evolution CMS, сниппет DocLister. Нужно боковое меню страниц одного раздела: выводить только детей текущего раздела, один уровень, без вложенности.
Разметка должна получиться такая: <ul
class="sidebar-nav__list">, внутри
<li> со ссылкой
class="sidebar-nav__link", а у текущей
страницы к ссылке добавляется
aria-current="page".
Напиши вызов сниппета с параметрами и чанки, которые в нём используются. К каждому параметру — строчку, что он делает, чтобы я мог поменять сам.
Получилось с третьего раза, и это нормально: первые два ответа были для MODX Revolution, где синтаксис другой. Помогла приписка «именно Evolution CMS, не Revolution» — в запросе выше она стоит с самого начала.
Просите нужную разметку сразу
Если не сказать, какой HTML вы хотите получить, нейросеть выдаст свой — с чужими классами, которых нет в ваших стилях. Приложите к запросу кусок готовой вёрстки и попросите повторить её один в один. Так ответ приходит сразу рабочим.
Что теперь понятно
- Чанк подставляется, сниппет выполняется и возвращает результат
- Готовых сниппетов хватает на меню, списки и крошки; форму пришлось написать свою
-
в других скобках считается заново, без кэша -
TV-поле добавляет странице своё поле и вызывается как встроенное:
[*cover*]