Прошлый раз статья про Twig была в «Экспериментах и исследования», с тех пор все, что было нужно, исследовали, и эксперимент успешно завершен. По итогу можно отметить такие плюсы использования Twig:
  • мощный шаблонизатор с кучей возможностей из коробки (при этом разработчик может добавить недостающий функционал несколькими способами) и подробной документацией;
  • дополнительная безопасность за счет того, что Twig по умолчанию экранирует весь вывод, а подсунуть со стороны пользователя тэги MODX не получится, так как шаблонизатору они глубоко безразличны;
  • все работает ровно так, как написано в шаблоне, не нужно вникать, что на каком этапе парсится;
  • шаблоны хранятся в файлах, а значит можно использовать GIT и полноценные редакторы, в которых предусмотрена подсветка синтаксиса Twig;
  • отпадает необходимость создавать в админке чанки и мелкие сниппеты; при желании можно легко подменять шаблоны в зависимости от каких-то параметров документа;
  • в два счета можно сменить дизайн прямо на работающем сайте;
  • полученный опыт пригодится в любой системе, использующей шаблонизатор (не обязательно Twig, но принципы работы у всех схожи), пусть даже MODX Revo;
  • вся суета, происходящая в парсере Evo, просто пройдет мимо вас (:
Бонусом к интеграции шаблонизатора прилагается кэшер, умеющий кэшировать в том числе и на время, с поддержкой разных кэш-провайдеров.

УстановкаДля установки необходимо наличие Composer. Для чего он нужен и как его установить — на эту тему немало статей в интернете. В OpenServer он уже установлен.

Открываем консоль, переходим в корень сайта и выполняем команду:
composer require pathologic/evo-twig

По этой команде Composer загрузит все необходимое и подготовит автозагрузчик классов:


Если Composer отработал успешно, то дальше нужно установить компонент EvoTwig. Взять его можно здесь: github.com/pathologic/evotwig

Компонент состоит из двух плагинов и сниппета.

Плагин replaceTemplateTwig, собственно, реализует интеграцию.

Плагин cacheDocumentObject кэширует данные страниц. Так как при полноценном использовании Twig кэширование страниц отключается, то было бы неплохо не дергать каждый раз базу для вывода страниц, что и делает этот плагин.

Сниппет getCache позволяет кэшировать вывод сниппетов, по ключу или на определенное время. Часто бывает нужно. Параметры этого сниппета:
  • snippetName — имя сниппета для запуска, необязательный параметр;
  • key — ключ кэша, обязательный параметр;
  • lifetime — время жизни кэша в секундах, если нужно кэшировать на время, необязательный параметр;
  • keyGenerator — имя сниппета или функция для генерации ключа, необязательный параметр.

НастройкаВсе настраивается в свойствах плагина replaceTemplateTwig:
  • Debug — включает режим отладки. При этом отключается кэширование страниц MODX, а в шаблонах Twig появляется возможность использовать функцию dump для вывода значений переменных.
  • MODX cache — разрешает кэширование MODX. Если включить при использовании Twig-шаблонов, то сайт станет почти статическим, поэтому по умолчанию отключено.
  • Disable Twig for templates — отключает Twig для шаблонов (: Но при этом остается возможность использовать Twig в чанках, загружать шаблоны (уже просто MODX-шаблоны) из файлов, а также кэшировать все, что под руку попадет.
  • Conditional — не очень понятная настройка, включение которой приведет к тому, что MODX будет отдавать при необходимости заголовки Last-modified и Etag.
  • Templates Folder — папка, в которой хранятся файлы шаблонов.
  • Templates Folder for Developers — то же самое, что и Templates Folder,
    но использоваться она будет, когда пользователь залогинен в админке. Пригодится при редактировании шаблонов на живом сайте — скопировали шаблоны в эту папку, отредактировали и после одобрения залили в основную папку.
  • Template extension — расширение у файла с шаблоном. По умолчанию tpl, потому что мне нравится так, но вообще принято вроде как .tpl.html или .html.
  • Cacher — здесь можно выбрать, каким образом кэшировать данные. По умолчанию используется файловая система. Бездумные эксперименты с этой настройкой могут закончиться крахом сайта (:
  • Allowed functions — здесь можно указать, какие PHP-функции разрешено использовать в шаблонах Twig.

ШаблоныКак уже говорилось, шаблоны хранятся в файлах и могут быть загружены разными способами:
  • файл выбирается в зависимости от шаблона документа и id документа. Для шаблона 2 и id 4 имя файла будет: tpl-2_doc-4.tpl;
  • файл выбирается в зависимости от id документа. Для id 4 имя файла будет: doc-4.tpl;
  • файл выбирается в зависимости от шаблона документа. Для шаблона 2 имя файла будет: tpl-2.tpl.
Очевидно, что такой подход во многих случаях неудобен. Поэтому файлы можно называть произвольно, а в содержимом шаблона в админке писать: @FILE:main.tpl, @FILE:article.tpl и т.п. Для документа с шаблоном _blank такой вызов можно написать прямо в содержимом документа.

Если файл шаблона не найден, то будет использоваться парсер MODX.

Теперь можно перейти к тому, что в этих шаблонах писать. Как и MODX, Twig использует несколько конструкций для вывода данных:
  • переменные — {{ var_name }}
  • функции — {{ function_name() }}
  • фильтры — {{ var_name | striptags | nl2br }}
  • управляющие элементы (теги) — {% if var_name == 'foo' %}{{ var_name }}{% endif %}
{% %} — такими скобками обозначаются условия, циклы и другие управляющие элементы шаблонизатора, а такие скобки {{ }} используются для вывода.

Разницу между MODX и Twig можно изобразить примерно так:
MODXTwig
[*pagetitle*]{{ resource.pagetitle }}
[+placeholder+]{{ plh.placeholder }}
{{ data.placeholder }} (при обработке чанков DLTemplate)
{{ modx.getPlaceholder('placeholder') }}
[(site_name)]{{ config.site_name }}
[!snippet? &foo=`bar`!]
{{ runSnippet('snippet', {foo:'bar'}) }}
{{chunkname}}{{ getChunk('chunkname') }}
{% include 'chunks/chunkname.tpl' %}
А вот ссылки на страницы можно использовать по-прежнему в стиле MODX: [~3~], то же самое относится и к служебным тегам [^qt^], [^q^], [^p^], [^t^], [^s^], [^m^].

Важное отличие от MODX — в шаблоне Twig переменная может быть чем угодно, не только строкой, а задать переменную можно прямо в шаблоне (в MODX это возможно только с помощью плагинов или сниппетов, которые устанавливают глобальные плейсхолдеры).

Все это подробно изложено в документации, поэтому остановлюсь на особенностях интеграции в Evo.

ПеременныеВ шаблонах страниц можно использовать переменные:
  • modx — тут понятно и так, объект DocumentParser, соответственно можно использовать все api-функции;
  • documentObject — массив $modx->documentObject, в котором содержится вся информация о документе;
  • resource — упрощенный вариант documentObject, в котором все поля хранятся в виде ключ-значение, включая и tv (resource.pagetitle, resource.longtitle, resource.price, resource['product-color'] — это есть в документации Twig, но еще раз обратите внимание, как происходит обращение к массиву);
  • debug — значение соответствующей настройки плагина;
  • config — массив настроек MODX;
  • plh — массив глобальных плейсхолдеров, которые задаются методом setPlaceholder;
  • ajax — по значению этой переменной можно определить был ли ajax-запрос к текущей странице (проверяется заголовок HTTP_X_REQUESTED_WITH);
  • _GET, _POST, _COOKIE, _SESSION — соответствующие массивы.

Для использования Twig в чанках нужно, для начала, чтобы эти чанки обрабатывались классом DLTemplate. То есть такая возможность есть, как минимум, в DocLister, FormLister и их производных. Чтобы применить к чанку Twig, к префиксу этого чанка нужно дописать T_:
&tpl=`@T_FILE:chunks/product` //загрузит из файла, обратите внимание, что имя файла без расширения; папка с файлами и расширение задаются отдельно
&tpl=`@T_CHUNK:product` //использует обычный MODX-чанк
&tpl=`@T_CODE:<p>{{ data.pagetitle }}</p>` //почему-то работает и такое


Какие переменные использовать в чанках, зависит от сниппетов, в которых эти чанки обрабатываются. В первую очередь переменные modx и data.
В DocLister добавится переменная DocLister c объектом контроллера.
В FormLister — аналогичная переменная FormLister, а также errors (массив с данными об ошибках), messages (массив сообщений контроллера), plh (массив плейсхолдеров формы).

Расширения TwigTwig можно расширять различными способами, поэтому к нему добавлено несколько полезных в Evo расширений.

Фильтр modxParserОбрабатывает строку парсером MODX.
{{ resource.content | modxParser }}
{{ '[*pagetitle*]' | modxParser }}


Фильтр pluralПредназначен для вывода существительных после числительных. Например, такой код выведет «Осталось 11 часов»:
{{ ['Остался %d час', 'Осталось %d часа', 'Осталось %d часов']|plural(11) }}

А такой — «Осталось 2 часа»:
{{ ['Остался %d час', 'Осталось %d часа', 'Осталось %d часов']|plural(2) }}


Функция makeUrlГенерирует ссылку на документ. Принимает три аргумента:
  • id документа,
  • массив параметров ссылки,
  • флаг типа ссылки, true — если нужно построить абсолютную ссылку, false — относительную (по умолчанию — true).
{{ makeUrl(2) }}
{{ makeUrl(2, {foo: 'bar'}) }}
{{ makeUrl(2, {}, true) }}
{{ makeUrl(2, {bar: 'foo'}, false) }}


Функция runSnippetЗапускает сниппет. Аргументами являются имя сниппета и массив параметров.

Функции getChunk, parseChunkВывод чанка и вывод чанка с обработкой. В первом случае функции передается имя чанка, во втором — имя чанка и массив параметров. В обоих случаях используется класс DLTemplate.

Также подключено расширение, которое позволяет использовать функции PHP, их список задается в соответствующей настройке плагина.

В общем-то добавлять собственные фильтры и функции в Twig несложно, описанные выше расширения простые и их можно использовать как пример. Для добавления расширений лучше всего создать плагин на события OnManagerPageInit, OnWebPageInit, OnPageNotFound и вызывать его после плагина replaceTemplateTwig.

На этом вводная часть закончена, вышеизложенного достаточно для старта, главное не лениться читать документацию. В следующих частях я возьму готовую верстку и покажу как я использую Twig на практике и почему больше не вернусь к парсеру MODX (: