Прокачиваем навык программирования на Fenom
Информация для разработчиков. Сложность средняя.
Практически все разработчики MODX используют тот или иной шаблонизатор. Большинство в рунете сделали свой выбор в пользу Fenom. Благодаря Василию конечно. Этот шаблонизатор достаточно простой и лёгкий. И его функционала хватает для решения практически всех своих задач. В этой статье мы посмотрим на него немного под другим углом и попробуем его возможности расширения.
Не так давно в pdoTools было добавлено событие «pdoToolsOnFenomInit». Думаю, не все осознали, что это событие даёт. Про собственные модификаторы уже писали. А если заглянуть в документацию Fenom, то можно увидеть, что возможности расширения очень большие. Давайте глянем на примеры.
В теги можно передавать параметры
Ещё пример. Можно легко добавить тег, который будет включать файловый чанк. Назовём его includeFile.
Ещё есть способ, как подсказывает Василий в комментариях, через плейсхолдеры. Главное, чтобы название не пересекалось с другими плейсхолдерами, ТВшками и т.п.
После выхода последней версии библиотеки modHelpers сделать этого достаточно легко и не надо заботиться о чистке сессии. Всё что нужно, добавить нужную переменную в контейнер, а затем феномом её вытащить.
Всё возможности в одной статье не опишешь. Но надеюсь, описанные приёмы пригодятся как опытным, так и начинающим разработчикам.
Практически все разработчики MODX используют тот или иной шаблонизатор. Большинство в рунете сделали свой выбор в пользу Fenom. Благодаря Василию конечно. Этот шаблонизатор достаточно простой и лёгкий. И его функционала хватает для решения практически всех своих задач. В этой статье мы посмотрим на него немного под другим углом и попробуем его возможности расширения.
Не так давно в pdoTools было добавлено событие «pdoToolsOnFenomInit». Думаю, не все осознали, что это событие даёт. Про собственные модификаторы уже писали. А если заглянуть в документацию Fenom, то можно увидеть, что возможности расширения очень большие. Давайте глянем на примеры.
Добавление пользовательской глобальной переменной
Это может пригодится, например, для много контекстных сайтов. При инициализации Fenom сразу определить нужные значения и использовать их потом в разметке.// Плагин
switch ($modx->event->name) {
case 'pdoToolsOnFenomInit':
$fenom->addAccessorSmart("site", "data", Fenom::ACCESSOR_PROPERTY);
// Переменные можно определить статически или динамически по условию
$fenom->data = [
"domain" => 'example.ru',
"support" => 'support@example.ru'
];
break;
}А затем в шаблоне добавить<div class="copyright">© <a href="//{$.site.domain}">{$.site.domain}</a></div>
<div class="support">Support <a href="mailto:{$.site.support}">{$.site.support}</a></div>Пользовательские теги
Добавлять свои собственные теги — офигенная вещь. Причем теги могут быть линейными (как например, include) и блоковыми ({if}...{/if}). Покажу на примере. Определим блок только для администраторов и добавим для этого блоковый тег can.<div>
{can}
{include 'chunkForAdministrators'}
{/can}
</div>Осталось подключить тег в плагине// Плагин
switch ($modx->event->name) {
case 'pdoToolsOnFenomInit':
$fenom->addBlockFunction('can', function (array $params, $content) {
if (user(user_id())->isMember('Administrator')) {
return $content;
} else {
return 'Данная информация только для администраторов!';
}
});
break;
}Может пример несколько надуманный, но он показывает возможности пользовательских тегов. Как вариант, можно добавить теги mobile, desktop. Ну в общем, надеюсь, понятно.В теги можно передавать параметры
// Плагин
switch ($modx->event->name) {
case 'pdoToolsOnFenomInit':
$fenom->addBlockFunction('can', function (array $params, $content) {
list($group, $param2) = $params;
if (user(user_id())->isMember($group) {return $content;}
});
break;
}А передают их так<div>
{can 'Administrator' 'param2'}
{include 'chunkForAdministrators'}
{/can}
</div>Ещё пример. Можно легко добавить тег, который будет включать файловый чанк. Назовём его includeFile.
// Плагин
$fenom->addFunction("includeFile", function (array $params) {
$file = MODX_CORE_PATH . 'elements/chunks/' . $params[0];
$output = '';
if (file_exists($file)) $output = chunk($file, $params[1]);
return $output;
});А в шаблоне пишем так:{includeFile 'chunk.tpl' ['var' => 'value', 'var2'=>'value2']} // указываем имя файла и массив плейсхолдеровFenom подключит файл core/elements/chunks/chunk.tpl и распарсит его.Разрешённые функции
В Fenom количество разрешённых php функций ограничено. Но можно самостоятельно добавить нужную функцию к списку разрешённых.switch ($modx->event->name) {
case 'pdoToolsOnFenomInit':
$fenom->addAllowedFunctions(['app']);
break;
}Заключение
Ну и напоследок расскажу ещё об одном приёме. Бывает иногда нужно прокинуть переменную в шаблонизатор. Т.е. в сниппете чего-то рассчитали или в классе и нужно передать в шаблон. Прямого способа я не знаю. Если есть, поправьте меня. Один из вариантов — сохранять в сессии, а в шаблоне доставать через $.session(). Способ спорный. Раздувать временными данными сессию, увеличивая тем самым и без того растущую как на дрожжах таблицу сессий. Желательно удалять их после использования. В общем, как-то не очень.Ещё есть способ, как подсказывает Василий в комментариях, через плейсхолдеры. Главное, чтобы название не пересекалось с другими плейсхолдерами, ТВшками и т.п.
После выхода последней версии библиотеки modHelpers сделать этого достаточно легко и не надо заботиться о чистке сессии. Всё что нужно, добавить нужную переменную в контейнер, а затем феномом её вытащить.
// Где-то в коде
$array = array('ids' => [1,2,3,4,5]);
$object = $modx->getObject('modResource', 100);
app()->instance('var.array', $array); // Добавляем префикс "var." для семантики, чтобы было понятно,
app()->instance('var.object', $object); // что это переменные.
// В шаблоне/чанке/ресурсе
{$array = app('var.array')}
{$object = app('var.object')}Всё возможности в одной статье не опишешь. Но надеюсь, описанные приёмы пригодятся как опытным, так и начинающим разработчикам.
Комментарии: 7
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
А насчет сессий и плейсхолдеров. Поправьте меня если я ошибаюсь, но у сессий больше время хранения. Один раз добавив что то в сессию, я могу вызвать эти данные когда угодно и где угодно (в пределах жизни сессии конечно). А можно ли использовать значение плейсхолдера после его получения на других страницах? По моему только на той странице, где мы этот плейсхолдер получили.
Я не говорю, что стоит использовать сесссии, лишь отметил разницу и возможное преимущество (сомнительное).
П.С. Добавил пример про линейный тег includeFile.
Для себя вывел такую вещь:
Вот на это всегда ругался то Pug (Jade), то redactor от modmore (imperavi), наровя преобразовать > в мнемонику html.
на что готовый ответ:
и работает через:
и больше никаких танцев с бубнами с преобразованием везде знака ">"