• Блог
  • Сравнение шаблонизаторов

Хочу поделится своим мнением о различных шаблонизаторах, которые на данный момент используются в MODX. Думаю, это будет интересно не только новичкам, но и опытным модыксерам, которые не задумываются об этой стороне дела. Итак, на сегодняшний день активно используются всего два шаблонизатора — встроенный и Fenom. Были попытки расширить этот список ещё парочкой — Smarty и Twig. Но если заглянуть в официальный репозиторий, то будет видно, что они давно уже не поддерживаются. Поэтому о них говорить не будем. Не так давно я также решил внести свою лепту и предложил сообществу компонент ZoomX, в котором из коробки идёт шаблонизатор Smarty. Только принцип его работы отличается от других, озвученных выше. Но об этом я расскажу дальше.

Шаблонизатор MODX

Этот шаблонизатор работает из коробки. Авторы MODX придумали интересную реализацию, не похожую на других. Контент многократно парсится с помощью регулярных выражений. Такой способ парсинга к сожалению накладывает большие ограничения на функциональные возможности. Поэтому логика в шаблонах минимальная и ограничивается в основном только фильтрами. Подразумевается, что сложная логика должна быть вынесена в сниппеты. Сниппет IF является ярким примером попытки добавить управляющую конструкцию в шаблонизатор. Выглядит, конечно, не очень.

Ещё ряд неудобств добавляют невозможность расширять шаблоны. А с развитием систем поддержки версионности и систем разработки (IDE) хранение основных элементов шаблонизатора в базе данных является сильным ограничительным фактором при выборе MODX в качестве CMS.

Но несмотря на эти недостатки этот шаблонизатор будет хорошим выбором при создании сайтов, в которых не планируется сложной логики в шаблонах, не стоит задача по поддержке версионности и постоянному деплою, а разработку можно вести в админке. Для портфолио, блогов и т.п. сайтов этот шаблонизатор подходит на все 100%.

Кстати!

Благодаря многократному парсингу контента шаблонизатор MODX позволяет не соблюдать строгую последовательность исполнения. Например, вы можете вставить тег плейсхолдера перед сниппетом, который его добавляет.

[[+someVar]]
...
[[!Snippet]]  // Определяет плейсхолдер someVar

На первой и второй итерациях парсер тег [[+someVar]] пропустит, а на третьей распарсит добавленным в сниппете значением.

Шаблонизатор Fenom

Если вам всё-таки нужна бОльшая свобода в реализации логики в шаблонах, то придётся использовать шаблонизатор помощнее. Компонент pdoTools с версии 2.0.0 предлагает Fenom. С его помощью вы можете реальзовать любую логику в шаблонах. Это полноценный PHP шаблонизатор. Он компилирует данный ему контент в php файл. Таким образом в нём можно использовать все конструкции языка PHP.

Но и тут есть свои недостатки. К сожалению, он не является самостоятельным шаблонизатором. Он добавляется в MODX в качестве дополнительного парсера контента. Таким образом в шаблонах доступны 2 синтаксиса и не все знают, в какой последовательности обрабатывается контент.

В сети можно найти вот такие примеры использования Fenom:

[[!pdoResources?
    &parents=`0`
    &tpl=`@INLINE <p>{$id} - {$pagetitle} {$createdon | dateago}</p>`
]]

На первый взгляд всё нормально. Но такой вызов вернёт неожиданный результат. Причина — первым контент парсит Fenom. Соответственно он обработает свои теги ({$id}, {$pagetitle} и {$createdon | dateago}) и вернёт вместо них пустые строки, так как этих плейсхолдеров ещё нет (планируется, что они появятся позже в INLINE чанке). Далее полученный контент обрабатывает парсер MODX. Только чанк уже распарсен и появившиеся плейсхолдеры вставлять некуда. Таким образом, вам не удастся пробросить в сниппет такую строку.

Такой вариант сработал бы, если бы вместо INLINE чанка был обычный или вызывался бы кэшируемый сниппет — на этой итерации (парсинг кэшируемых тегов) Fenom не запускается.

Или вот недавно меня спросили, почему не выводится статистика

[[!siteStatistics? &toPlaceholders=`1`]]
<div>{$_modx->getPlaceholder('stat.views') | declension : 'просмотр|просмотра|просмотров' : true}</div>

Ответ тот же — очерёдность парсинга. И так на каждой итерации. И вы никак не сможете исключить подобные ошибки.

Очевидным решением будет использование только тегов Fenom. Но есть ещё ряд моментов с кэшированием и файловыми элементами. Некоторые уже наступили на эти грабли. Я подробно рассказывал про шаблонизаторы MODX и Fenom в этом видео.

Кстати, что интересно, Fenom добавлен в pdoTools много лет назад, но ни один сниппет из этой библиотеки не поддерживает полноценную работу с ним. Поэтому приходится делать такой финт.

Если покопать дальше, то найдётся ещё пара вопросов типа компиляции всех чанков на каждый запрос и компиляции страницы на каждой итерации MODX парсера. Но это технические вопросы касающиеся оптимизации. Верстальщикам как правило до этого нет дела. Да и при расширении шаблонов придётся делать лишний запрос к БД.

В общем, Fenom добавил в MODX больше возможностей для разработки и интеграции вёрстки, а pdoTools улучшил ряд моментов в MODX для более оптимальной работы Fenom.

Шаблонизатор Smarty

С выходом моего компонента ZoomX в MODX можно верстать используя шаблонизатор Smarty. Но я не стал повторять реализацию Fenom. Мы много лет говорим о том, что MODX отстаёт от современных подходов разработки. Поэтому в моей реализации Smarty полностью заменяет шаблонизатор MODX и работает именно так, как он был задуман — однократная компиляция контента. И благодаря Opcache скомпилированный шаблон запускается мгновенно. Я показывал результат обработки 100 ресурсов с одним чанком аналогично этому тесту Fenom. Прирост скорости свыше 50%. Тест, конечно, искусственный, но даёт сравнительное представление по отношению к тесту Fenom.

Ещё важное отличие от реализации Fenom — Smarty заточен под файлы. Т.е. инструкция {include 'index.tpl'} загрузит файл, а не чанк из базы данных в случае Fenom. В современной разработке никто не работает с кодом из базы данных. В ней держат только информацию.

В процессе знакомства со Smarty я могу отметить некоторые преимущества перед Fenom. Например, в Smarty можно легко перенести концепцию кэширования элементов и тегов. В MODX это делается добавлением восклицательного знака вначале тега. В Smarty в тег добавляется атрибут nocache или код заключается в аналогичный блок. Таким образом вы получаете скомпилированный шаблон с динамическим куском кода. Fenom так не умеет. Поэтому он вынужден использовать концепцию MODX со знаком "!" — проверять наличие вначале имени этого знака. Но согласитесь, такая запись {$_modx->runSnippet('!Snippet')} выглядит хуже [[!Snippet]]. В последнем случае мы визуально имя отделяем от знака "!". Но и эта логика не доработана. В тех же файловых элементах с этим проблема — некуда добавлять восклицательный знак. Поэтому они всегда кэшируются.

Ещё в Smarty очень удобный механизм добавления плагинов (функций, модификаторов и т.д.). Он проще и оптимизирован под работу по требованию. Ну и если сравнить по функциональности, то Smarty также имеет преимущества перед Fenom.

Заключение

Вот такой беглый анализ. Выбирайте шаблонизатор в зависимости от задачи. Лично мне близок подход разработки из мира фреймворков. Поэтому я, конечно, выбираю последний вариант. Такой же принцип используется и в October CMS, а также внедрили в Evolution CMS. В ближайшее время я планирую добавить в ZoomX библиотеку инструментов наподобие pdoTools. И после этого перевести сайт на Smarty. Постараюсь всё это заснять на видео.

0   331

Комментарии ()

  1. shock 20 января 2021, 21:12 # +1
    Спасибо, за обзор, Сергей!
    Да и за развитие MODX в этом направлении, спасибо.
    Библиотеку инструментов планируете создать, используя PDO?
    1. Сергей Шлоков 20 января 2021, 21:30 # 0
      Мы одной крови!;)

      Библиотеку инструментов планируете создать, используя PDO?
      Не, это слишком накладно писать свою ORM. Есть мысли прикрутить Eloquent. Тут ещё предстоит оценить фронт работ. А работы явно будет много. Но есть большое желание отказаться от xPDO. Для начала можно сделать слой абстрации, чтобы можно было переподключать ORM.

    Вы должны авторизоваться, чтобы оставлять комментарии.

    Выделите опечатку и нажмите Ctrl + Enter, чтобы отправить сообщение об ошибке.