Шаблонизатор Fenom для MODX

Шаблонизатор Fenom – это надстройка для MODX Revo, включённая в состав пакета pdoTools. Позволяет полностью заменить "родные" теги MODX с увеличением скорости и удобства работы с информацией из таблиц базы данных и значительно расширить возможности шаблонизации.

Для тех, кто начинал изучение MODX по официальной документации, поначалу работа с Fenom может показаться неудобной и более сложной, а, открыв первый раз сайт на Fenom, вообще не сообразить, что и как работает.

Это быстро проходит) и, возвращаясь при необходимости к стандартным тегам, начинает не хватать возможностей парсера pdoTools.

Включение Fenom

Для того, чтобы теги Fenom начали обрабатываться в шаблонах, чанках и тексте ресурса, нужно включить следующие настройки: Системные настройки - pdotools:

Базовые настройки Fenom

Шаблонизатор имеет такую особенность – если парсер не может обработать страницу, она может выйти пустой, либо с исходными тегами. Причина пишется в Журнале ошибок. Первоначально, нужно обратить внимание на инлайновые стили и скрипты Java, потому что парсер срабатывает на фигурные скобки {}.

Для указания парсеру Fenom фрагментов, не подлежащих обработке, используются теги {ignore}фрагмент{/ignore}. Помогает не всегда, это связано с особенностями работы парсера.
Часто бывает проще расставить пробелы или переносы строки после открывающей скобки и перед закрывающей.

Базовые понятия

Основные источники информации по работе с Fenom – в документации modx.pro и в исходной документации.

Желательно сразу освоить файловые элементы (официальное руководство).

Начнём с шаблонов. По умолчанию, путь к файлам core/elements(папку elements нужно будет создать). Дальше, на усмотрение, кому как удобно.

Например, создадим папки templates, chunks и snippets (в директории elements, понятное дело). Пускай базовый шаблон будет main.html(или с расширением tpl, неважно). Весь текст, соответственно, будет храниться в файле core/elements/templates/main.html.

Для связи со структурой MODX нужно будет создать обычным способом шаблон, в поле Код шаблона которого записывается ссылка на файл в виде {include 'file:templates/main.html'}.

Шаблон главной страницы в файле

Чанки и сниппеты в админ панели создавать не нужно. Файловый чанк прописывается в шаблоне через include{include 'file:chunks/header.html'}, или insert, запуск сниппета из файла – {'@FILE snippets/cache.php' | snippet}.

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

Как работает наследование и расширение шаблонов (чанков) в Minishop2 можно увидеть на примере чанков писем. Здесь 6 видов оповещений построены на 1 базовом шаблоне.

Аналоги тегов MODX

Поля текущего ресурса (теги со *): {$_modx->resource.id}, {$_modx->resource.pagetitle}, {$_modx->resource['description']}, либо {$_modx->resource['имя_тв_поля']} и т.д. (разные варианты обращения к элементам массива $_modx->resource).

Плейсхолдеры сниппета (теги с +): {$id}, {$longtitle}

Системные настройки (теги с ++): {'site_url' | option} или {$_modx->config['site_url']}

Ссылка на ресурс (теги с ~): {88 | url}. Например, генерация абсолютной ссылки на документ с id = 88, [[++site_url]][[~88]] = {'site_url' | option ~ (88 | url)} или {'site_url' | option}{88 | url)} (в Fenom символ ~ выполняет объединение строк)

Поля любого ресурса: {11 | resource : 'longtitle'}

Вызов сниппета: {'pdoSitemap' | snippet},
некешированный {'!pdoSitemap' | snippet},
с параметрами {'!pdoMenu' | snippet : ['parents' => 0, 'resources' => '-1,-6', 'showHidden' => 1]}

Поля любого пользователя по его id: {5 | user : 'fullname'}

Массив полей текущего пользователя $_modx->user. Например, посмотреть все поля {$_modx->user | print}

Закомментировать теги Fenom можно так: {*'!pdoPage' | snippet*}

Разумеется, это не все возможности шаблонизатора, есть ещё масса модификаторов, полностью заменяющих "родные" теги MODX и расширяющие их функции.

Условия и циклы

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

Условия в Fenom задаются так же, как в большинстве языков программирования:

условие if:

{if $_modx->resource.parent == 1}
        {$_modx->resource.pagetitle}
    {elseif $_modx->resource.parent == 5}
        {$_modx->resource.longtitle}
    {else}
        Другой текст заголовка
{/if}

использование логических И (&&), ИЛИ (||) и группировка условий (тут же пример присвоения значения переменной):

{var $u = 5}{var $e = 9}
        {if $u > 2 || ($e >= 3 && $e < 100)}
            Выполненное условие
{/if}

короткая запись if (тернарный оператор),

{$_modx->resource.longtitle ? $_modx->resource.longtitle : $_modx->resource.pagetitle}

или аналог стандартного default в случае пустого значения:

{$_modx->resource.introtext ?: 'аннотация не заполнена'}

условие switch:

    {switch $_modx->resource.id}
        {case 5}     
            Текст
        {case 7,8}
            Другой текст
        {case default}
            Пусто
    {/switch}

Полноценный цикл foreach:

{var $array = [0 => 'val1', 1 => 'val2']}
{foreach $array as $key => $value}
    key = {$key}, value = {$value}
{/foreach}

Пример вывода дочерних ресурсов без вызова сниппета

В Fenom переменная $_modx – обращение к классу microMODX, имеющему несколько очень полезных методов.

перенаправление на заданный url, либо ресурс (здесь, с id = 101) {$_modx->sendRedirect(101 | resource : 'uri')}

получение потомков документа (здесь, id документа 47, глубина вложенности 1). Поскольку возвращает массив, для наглядности показан с простым выводом на экран. {$_modx->getChildIds(47, 1) | print}

То же, для родителей документа $_modx->getParentIds()

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

{var $parents = $_modx->getResources(
    ['published' => 1, 'deleted' => 0, 'isfolder' => 1],
    ['sortby' => 'menuindex', 'select' => 'id,pagetitle'])}
{foreach $parents as $parent}
    {var $childs = $_modx->getResources(
    ['published' => 1, 'deleted' => 0, 'parent' => $parent.id], 
    ['select' => 'pagetitle', 'sortby' => 'menuindex'])}
        {if $childs}
            <div>
                <h5>{$parent.pagetitle}</h5>
                    {foreach $childs as $child}
                        <div>
                            {$child.pagetitle}
                        </div>
                    {/foreach}
            </div>
        {/if}
{/foreach}

Этот пример показывает, как, пользуясь только средствами Fenom, вывести дочерние ресурсы, сгруппированные по родительскому документу.

Произвольная группировка товаров и порядок вывода категорий miniShop2 в корзине

Товары в корзине выводятся с помощью сниппета msCart, чанк вывода, по умолчанию, tpl.msCart. Добавленные в корзину покупки хранятся в переменной $_SESSION в таком виде:

[minishop2] => Array
        (
            [cart] => Array
                (
                    [19540dc928fb772d846a78d33c108a6e] => Array
                        (
                            [id] => 821
                            [price] => 150
                            [weight] => 0
                            [count] => 1
                            [options] => Array
                                (
                                )
                            [ctx] => web
                        )
                    [9537fcc265888919ea41499d68ce0317] => Array
                        (
                            [id] => 371
                            [price] => 400
                            [weight] => 0
                            [count] => 1
                            [options] => Array
                                (
                                    [prs] => 400
                                    [age] => 3-6
                                    [month] => 400
                                )
                            [ctx] => web
                        )
                    [c158d4dca43e0a30c567c0b2f415d04e] => Array
                        (
                            [id] => 822
                            [price] => 400
                            [weight] => 0
                            [count] => 1
                            [options] => Array
                                (
                                )
                            [ctx] => web
                        )
                )        
    

Где ключ элемента массива с покупкой, например, такой [c158d4dca43e0a30c567c0b2f415d04e], формируется динамически при добавлении товара в корзину при помощи функции md5 следующим образом: $key = md5($id . $price . $weight . (json_encode($options))); (исходник).

Соответственно, товары в корзине выводятся по очерёдности их добавления, без учёта id товара, либо его категории.

Стандартный чанк tpl.msCart сделан на Fenom, поэтому, можно, с минимальными изменениями, задать нужную группировку и порядок вывода категорий товаров.

Чанк принимает массив товаров $products, поэтому в чанке, до цикла {foreach $products as $product} (это 16 строка), раскидываем общий массив на несколько массивов категорий, например, cat_15 и cat_16, где число – id категории.

{foreach $products as $product}
    {if $product.parent == 15}
        {set $cat_15[] = $product}
    {elseif $product.parent == 16}
        {set $cat_16[] = $product}
    {else}
        {set $other_products[] = $product}
    {/if}
{/foreach}

И вывод товаров из категорий:

{if count($cat_15)}
    {foreach $cat_15 as $product}
        {*здесь вывод товара*}
    {/foreach}
{/if}
{if count($cat_16)}
    {foreach $cat_16 as $product}
        {*аналогично стандартному выводу*}
    {/foreach}
{/if}
{if count($other_products)}
    {foreach $other_products as $product}
        {*внутри цикла foreach (строки 17...69)*}
    {/foreach}
{/if}

Таким образом можно не только определить последовательность вывода категорий товаров, но и задать общий заголовок и футер товаров одной категории и использовать разное оформление.

Привилегия.ру

Метки: modx revolution