Fenom VS Smarty
Недавно Михаил попросил меня написать сравнительный обзор Fenom и Smarty. Честно сказать, я феномом не пользовался, и хотя сейчас уделил время на какое-то его изучение, все-таки не смогу выдать какое-то сильно аргументированное заключение, просто потому что много в феном мог и не увидеть (хотя оно там может даже и есть). Тем не менее, я приведу несколько примеров использования Smarty, которые довольно часто используются на практике, но которых я не увидел в Феноме, а те, кто хорошо знает Феном, пусть поправят меня или подтвердят.
Для начала следует отметить, что все-таки эти инструменты хоть и схожие, но изначально судя по всему ориентированы на разные цели. Феном (в рамках pdoTools) на родные MODX-сущности (чанки, шаблоны и т.п.), а Смарти (в том числе и в рамках modxSmarty) на работу с файлами. Потому, еще раз, их немного сложно сравнивать. Ну да ладно, это все лирика. Разберем лучше на реальных примерах.
Одновременно несколько директорий шаблонов (скинов).
Что в первую очередь искал в феноме, но не увидел — это работа с несколькими директориями шаблонов. Тут стоит оговориться, что я имею ввиду разделы в файловой системе, но это может быть и какое-то другое групповое отличие. В любом случае, идея в том, чтобы можно было не просто одним чанком расширить другой чанк, а одну группу чанков сменить другой группой чанков, чтобы получить совершенно новое оформление. Приведу пример, как это работает в Смарти. К примеру, у нас есть вот такая структура joxi.ru/KAxeRO7c4n0JGr
Здесь у нас есть основной полноценный шаблон (скин сайта) shopmodx с кучей шаблон-файлов. Так вот, если я хочу какие-то шаблон-файлы основного скина переопределить (полностью или частично), мне не обязательно где-то что-то модифицировать. Мне достаточно Смарти добавить еще одну (а можно и не одну) директорию шаблонов, и смарти при вызове шаблонов будет перебирать все эти директории, пока не найдет запрошенный шаблон.
…
На самом деле ряд моментов я опущу, так как все это такие тонкости, которые на конкретных задачах рассматриваются. Но вот сегодня дополнительно тестировал Феном и столкнулся с парой неприятных для меня моментов:
1. Вызов произвольных функций.
К примеру, в Смарти я легко могу написать {print_r($array)}, или {array_sum([1,3,4,6,7])}. Вот в Феном я этого не смог сделать. Ошибка. Вопрос: он вообще это умеет делать?
2. Доступ к объекту $modx
Вот это вообще тема… Довольно часто я в шаблонах обращаюсь к API MODX. Например, {if $modx->user->id} это проверка наличия пользователя. Если пользователь в админке авторизовался, то он и во фронте будет виден и все политики для него будут работать. А вот {if $modx->user->isAuthenticated()} будет себя иначе вести, так как этот метод проверяет, авторизован ли пользователь именно в этом контексте (по умолчанию web), а так как авторизовавшись в админке пользователь авторизован только в контексте mgr, то во фронте при такой проверке пользователя не будет.
Другой пример {if $modx->resource->Parent->published}, то есть я в шаблоне просто хочу проверить опубликован ли родитель текущего документа или нет. И вот в Феном я этого просто так не могу сделать (на самом деле могу, но это далее). То есть у меня просто нет объекта {$modx}. Есть объект {$_modx}, но это вообще мало отношения к $modx имеет, так как это кастомный тонкий клиент между шаблоном и реальным объектом $modx. К слову, вот это у меня больше всего вопросов и вызвало. Зачем прятать объект $_modx->modx? Зачем он приватный? Ведь так мы теряем полноценный доступ к API MODX. Для секурности? Но полноценной секурности здесь нет, ибо ничто мне не мешает обратиться к $modx через объект {$_modx->lexicon->modx} или {$_modx->cacheManager->modx}, а вот головной боли мне это серьезно добавляет и урезает творческую реализацию.
В общем, надо будет еще все это как следует погонять. Но так или иначе, Феном все-таки тоже весьма не плохо, хотя мне и не получается пока на нем разгуляться.
Для начала следует отметить, что все-таки эти инструменты хоть и схожие, но изначально судя по всему ориентированы на разные цели. Феном (в рамках pdoTools) на родные MODX-сущности (чанки, шаблоны и т.п.), а Смарти (в том числе и в рамках modxSmarty) на работу с файлами. Потому, еще раз, их немного сложно сравнивать. Ну да ладно, это все лирика. Разберем лучше на реальных примерах.
Одновременно несколько директорий шаблонов (скинов).
Что в первую очередь искал в феноме, но не увидел — это работа с несколькими директориями шаблонов. Тут стоит оговориться, что я имею ввиду разделы в файловой системе, но это может быть и какое-то другое групповое отличие. В любом случае, идея в том, чтобы можно было не просто одним чанком расширить другой чанк, а одну группу чанков сменить другой группой чанков, чтобы получить совершенно новое оформление. Приведу пример, как это работает в Смарти. К примеру, у нас есть вот такая структура joxi.ru/KAxeRO7c4n0JGr
Здесь у нас есть основной полноценный шаблон (скин сайта) shopmodx с кучей шаблон-файлов. Так вот, если я хочу какие-то шаблон-файлы основного скина переопределить (полностью или частично), мне не обязательно где-то что-то модифицировать. Мне достаточно Смарти добавить еще одну (а можно и не одну) директорию шаблонов, и смарти при вызове шаблонов будет перебирать все эти директории, пока не найдет запрошенный шаблон.
…
На самом деле ряд моментов я опущу, так как все это такие тонкости, которые на конкретных задачах рассматриваются. Но вот сегодня дополнительно тестировал Феном и столкнулся с парой неприятных для меня моментов:
1. Вызов произвольных функций.
К примеру, в Смарти я легко могу написать {print_r($array)}, или {array_sum([1,3,4,6,7])}. Вот в Феном я этого не смог сделать. Ошибка. Вопрос: он вообще это умеет делать?
2. Доступ к объекту $modx
Вот это вообще тема… Довольно часто я в шаблонах обращаюсь к API MODX. Например, {if $modx->user->id} это проверка наличия пользователя. Если пользователь в админке авторизовался, то он и во фронте будет виден и все политики для него будут работать. А вот {if $modx->user->isAuthenticated()} будет себя иначе вести, так как этот метод проверяет, авторизован ли пользователь именно в этом контексте (по умолчанию web), а так как авторизовавшись в админке пользователь авторизован только в контексте mgr, то во фронте при такой проверке пользователя не будет.
Другой пример {if $modx->resource->Parent->published}, то есть я в шаблоне просто хочу проверить опубликован ли родитель текущего документа или нет. И вот в Феном я этого просто так не могу сделать (на самом деле могу, но это далее). То есть у меня просто нет объекта {$modx}. Есть объект {$_modx}, но это вообще мало отношения к $modx имеет, так как это кастомный тонкий клиент между шаблоном и реальным объектом $modx. К слову, вот это у меня больше всего вопросов и вызвало. Зачем прятать объект $_modx->modx? Зачем он приватный? Ведь так мы теряем полноценный доступ к API MODX. Для секурности? Но полноценной секурности здесь нет, ибо ничто мне не мешает обратиться к $modx через объект {$_modx->lexicon->modx} или {$_modx->cacheManager->modx}, а вот головной боли мне это серьезно добавляет и урезает творческую реализацию.
В общем, надо будет еще все это как следует погонять. Но так или иначе, Феном все-таки тоже весьма не плохо, хотя мне и не получается пока на нем разгуляться.
Комментарии: 45
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Это для безопасности — вдруг на сайте есть контент-менеджер, который может править чанки.
Fi1osofЕсли вдруг кто тоже не сразу нашел: joxi.ru/82QV3dNu1DovgA
Ну, как я и сказал, есть как минимум {$_modx->cacheManager->modx}, хотя и можно это тоже перекрыть. А второе: админка в MODX — это уже зона риска огромная, так что нефиг туда вообще никого лишнего пускать :)
Суть в том, что пользоваться {$_modx} можно давать кому угодно, он только для чтения, грубо говоря. Тогда как через {$modx} можно легко убить всю систему. По этой же причине и php функции отключены по умолчанию.
Fi1osofИ вот такой вопрос: Есть два чанка fenom1 и fenom2. В документе пишу [[$fenom]] и ок, на странице все выводится. Но если я в чанке fenom1 пишу {extends 'fenom2'}, то он расширяет второй чанк, но на странице выводится только содержимое чанков (ничего более от шаблона). Можно как-то расширять другие чанки или что я не так делаю? Шаблоны корректно расширяются.
Или прям расширяешь его?
А то недавно Иван Климчук заметил, что без переопределения хотя бы одного блока ничего не работает и дописал это в доки.
Fi1osofjoxi.ru/a2XVypGuy0Bzjr
joxi.ru/ZrJVWD0u13PO4r
По всякому игрался, результат один и тот же.
Fi1osofПосмотри, может где-то какие-то ошибки в логах есть? По идее, всё должно расширяться без проблем — сам этим пользуюсь постоянно на разных проектах.
Чанк с расширением нужно вызывать некэшируемым:
Или можно так:
Тогда никаких белых страниц, всё работает.
Fi1osofОбновляем страницу и получаем такой результат: joxi.ru/VrwoaO9IKVPyXr
То есть это весь код шаблона и страницы, и в нем код чанка fenom1 как есть, вместе с расширением {extended}. То есть расширение уже становится не чанка, а по сути шаблона. В общем, контекст не тот уже.
Здесь надо мыслить как с этим поступить. Самое правильное, как мне кажется — это даже в рамках шаблона отрабатывать чанки сразу. Или договориться о том, что нельзя использовать кешируемые чанки с расширением других чанков.
К слову, Смарти не позволяет декларирование {extends} иначе как в начале кода. А тут он де факто получается внутри.
Вызов Fenom чанков через Fenom синтаксис работает без проблем — лучше так и делать =)
Fi1osofТеперь, насколько я вижу, из {$_modx} до modX добраться не выйдет. Спасибо, что указал на эту уязвимость!
Fi1osofВот я отключил в настройках доступ к $modx и выполнение php. ОК. А теперь я хоть в чанке, хоть в контенте документа (не имея доступа к чанкам и т.п.) пишу вот такое:
Что я здесь делаю, не трудно догадаться: я просто перетираю кеш системных настроек MODX-а с новыми значениями настроект. И при повторном заходе на страницу (с перезаписанными настройками), я уже могу делать все, что угодно, включая {$modx->user->sudo = 1} {$modx->user->save()}. Сорри, но это ппц какая дыра в безопасности.
Хотя нет, не отключать, а просто запретить указывать такие настройки. Выложил новую версию, в которой параметр $options у cacheManager::set() не используется. Итого, кэш получать можно любой, а сохранять только в default.
Твой ход =)
Fi1osofА доступ в {$_modx} включен по умолчанию и он должен быть безопасным. Сегодня ты очень сильно помог в этой задаче. Надеюсь, что больше никаких уязвимостей при конфигурации по умолчанию не найдётся.
Если же разработчик (не редактор) хочет — он может смело всё включить. Но он должен это сделать сам, понимая, чем рискует.
Fi1osofВызов в шаблоне:
{$_modx->runSnippet('temp')}
Сниппет:
<?php
$output = $modx->getChunk('testChunkCommon', array('some_placeholder' => 'some_placeholder'));
return $output;
Содержимое testChunkCommon.tpl:
1: {$some_placeholder}
2: {$_pls['some_placeholder']}
3: {$_modx->getPlaceholder('some_placeholder')}
4: [[+some_placeholder]]
Результат:
1:
2:
3:
4: some_placeholder
Значит, проблем с обработкой плейсхолдеров Fenom в чанке нет.
Если я неправильно понимаю, чего ты хочешь добиться — покажи свою проблему на чистом тестовом сайте.
Зато все значения выводятся при вызове сниппета [[!temp]]
Тестовый сайт:
s3660.h2.modhost.pro/test.html
user: s3660
pass: a0VU4iiGhkmb
С каких это пор сам MODX научился работать с Fenom?
P.S. Вот теперь fenom будет у меня повсюду :)
Но всё же это не решает проблему с сниппетами, которые писал не я, например с Office или HybridAuth — у них точно такая же проблема с плейсхолдерами.
Ждать вторую, более развернутую часть сравнения?
Fi1osofБолее развернутую? Вряд ли. При включенных $modx и php в рамках самого MODX API и php никаких отличий не может быть. А по поводу отличий на уровне самой шаблонизации я в топике писал:То есть какие-то моменты я уже начал писать, но потом стер, так как все-таки под разные задачи создавались эти модули. Феном уступает в некоторых моментах (пару примеров все-таки ниже приведу), но зато он добавляет логику на уровне самих MODX-шаблонов и чанков. modxSmarty мощнее в плане самой шаблонизации, но не отрабатывает смарти-теги в самих MODX-шаблонах и чанках (хотя техническая возможность на самом деле есть, и если есть интерес к этому, это можно обсудить отдельно).
По поводу более расширенных возможностей Смарти:
Пример 1. Скрываемые блоки hide.
В основном шаблоне мы пишем
Во-первых, я не увидел в Феноме возможность указывать дочерние блоки. То есть можно в расширяющем шаблоне в блоке прописать {parent} и туда выведется родительский блок, но нельзя указать {child}, чтобы туда вывелось содержимое дочернего блока.
Во-вторых, интересен блок hide (его можно использовать и без $smarty.block.child, он от него не зависит) — если в расширяющем шаблоне нет этого блока или содержимое блока будет пустым, то и родительский блок не выводится. В нашем случае, если в расширяющем шаблоне не будет определен сам баннер, то и базовое обрамление тоже не будет выведено.
Пример 2. Инклюды с кешированием.
Тоже этого не увидел в Феноме.
Всем известно, что MODX кеширует конечный код для каждой страницы в отдельности. То есть даже если у вас кешируемый чанк, то на каждой отдельной странице при первом заходе он будет отрабатываться. Но если вещи, которые вообще не меняются на всем сайте (например, подвал). В Смарти я могу вот так легко сделать: {include $template cache_id=«footer»} и этот шаблон будет вызван только один раз, а все остальные вызовы будут уже из кеша.
Fi1osofFi1osofВасилий, это будет исправлено?
то выведет "-1 day"
Fi1osof{$ts|date_format:"%Y/%m/%d %H:%M:%s"} — работает
{$ts|date_format:"-1 day"} — не работает
Fi1osofОК, если у вас там нет ковычек, тогда уже вопрос к самому феному.
Попробуйте
Вобщем так работает
{set $date = strtotime('+10 days')}
{$date|date_format:'%d %b %Y'}
1) date() в феноме модификатор и первый аргумент тут дата или timestamp, а второй — формат
2) При вызове модификатора date_format, %s (в нижнем регистре) возвращает timestamp. Нужно юзать %S
Варианты записи: