mmxFenom - нативная интеграция шаблонизатора

Продолжаю разработку новой вселенной дополнений для MODX и сегодня у нас на очереди шаблонизатор Fenom.

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

Однако, с течением времени компонент оброс огромным количеством функций и сейчас его разрабатывать очень трудно. Где-то поменяешь одно — сломаешь другое.

Да и с появлением mmxDatabase, как мне кажется, какие-то упрощённые выборки из БД просто теряют актуальность. Ведь сегодня можно в любом сниппете делать вот так:
$resources = MMX\Database\Models\Resource::query()
  ->where('published', true)
  ->select('id', 'pagetitle')
  ->get()
  ->toArray();

return print_r($resources, true);
Не хватало только шаблонизатора для подобных выборок — и теперь он тоже есть.

Быстрый старт


Устанавливаем как обычно:
composer require mmx/fenom
composer exec mmx-fenom install

Дальше в нашем примере выше меняем возврат результата:
return $modx->services->get('mmxFenom')
  ->fetch($tpl, ['resources' => $resources]);

Создаём простенький чанк tplResources
{foreach $resources as $resource}
  {$resource | print}
{/foreach}

И указываем его при вызове:
[[!listResources? &tpl=`tplResources`]]

Вот, в принципе, и всё!

Что нового


1. При каждом обращении к сервису mmxFenom вы получаете независимый инстанс!

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

Поэтому прямо в сниппете можно добавлять свои функции или модификаторы, которые нужные именно для вашей логики:
$service = $modx->services->get('mmxFenom');
$service->addModifier('hello', static function($var) {
  return $var . ' World!';
});
    
return $service->fetch($tpl, ['var' => $var]);

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

2. Через это в шаблонизаторе нет никаких лишних функций и модификаторов. Нет инициализации переменных MODX, быстрого парсинга его тегов — вообще ничего лишнего.

Всё, что нужно, вы добавите в своём сниппете или компоненте. И укажете в документации, что можно использовать.

Работать это будет однозначно быстрее, чем реализация в pdoTools, которая при каждом запуске получает текущий ресурс со всеми ТВ — а вдруг вам понадобится?

3. Отсутствие своего парсера.

Новый Fenom не вмешивается в логику работы системы. Теперь нельзя включить системную настройку и использовать новый синтаксис везде. Надо вам использовать Fenom — вызывайте свой сниппет.

Да, это может быть не очень удобно, но избавляет от огромного количества проблем с рендером.

4. Наконец-то правильное кэширование всех элементов, которое следует из предыдущего пункта.

Вызванные через сниппеты куски кода нормально сохраняется в кэше документов. А заодно статические шаблоны и чанки обрабатываются вообще без участия MODX.

Если к элементу привязан файл, то читается именно файл, а не данные в БД. Время обновления элемента тоже определяется по этому файлу. Если же элемент не статичный, то из специальной таблички читается время его последнего обновления (которое сохряняется туда плагином, потому что MODX эти данные не хранит).

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

5. Можно использовать плейхолдеры MODX.

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

То есть, если вам надо вывести в чанке Fenom название текущей страницы, не стесняйтесь использовать родной плейсхолдер:
<h1>[[*pagetitle]]</h1>

{foreach $resources as $resource}
  {$resource | print}
{/foreach}

Естественно, условия и прочие циклы надо писать на Fenom.

5. Через системные настройки можно включить полный доступ к MODX и PHP через аксессоры.

<p>Today is {$.php.date('Y-m-d H:i:s')}</p>
<p>Current id of MODX resource is: {$.modx->resource->id}</p>

Никакого костыльного класса microMODX! Не устраивают системные плейсхолдеры — врубайте полный доступ и воротите, что хотите. Вплоть до удаления исходников сайта, это уже на ваше усмотрение.

6. Если что-то в чанке что-то не так, никаких больше белых страниц.

На месте вывода проблемного чанка будет просто пустота и примерно такая запись в журнале ошибок.
[mmxFenom] Unknown accessor '$.php' in tplResources line 3, near '{$.php' < — there
7. Три источника шаблонов

Больше никаких созданий чанков на лету, чтения разными способами через @FILE и прочего.

Ровно 3 варианта:
  • Циферка или название — это id или имя чанка MODX
  • Циферка или название c префиксом template: — это шаблон MODX
  • Путь с префиксом file: — это реальный файл на диске, никак с MODX не связанный. Родной механизм для Fenom.
Пример вызова:
$data = ['var' => 'string'];
$fenom = $modx->services->get('mmxFenom');

$html1 = $fenom->fetch('tplTest', $data); // Чанк MODX с именем tplTest
$html2 = $fenom->fetch('template:1', $data); // Шаблон MODX с id = 1 
$html3 = $fenom->fetch('file:chunks/name', $data); // файл из core/elements/chunks/name.tpl
$html4 = $fenom->fetch('file:name.html', $data); // файл из core/elements/name.html

Напоминаю, что статические элементы MODX в первую очередь работают с привязанными файлами.

Заключение


Как вы можете видеть, это моя работа над ошибками. Меньше универсальности, больше понятной логики и возможностей.

У знатоков может возникнуть вопрос, почему здесь версия Fenom всё еще 2? А потому, что 3ю версию я не смог заставить нормально работаь. Она банально глючит, и автор не вносил изменений уже больше года.

При том, что 3я версия так и не избавилась полностью от eval(), я не вижу смысл упахиваться и делать какой-то свой форк для исправления проблем. Нынешняя 2я версия уже давно доказала свою стабильность.

Ну и заодно наш новый пакет можно использовать даже с PHP 7.4!

Поставить плюсики и создать issues можно в репозитории — github.com/bezumkin/mmx-fenom

Поддержать произвольной суммой через СБП можно здесь.
Василий Наумкин
02 мая 2024, 11:51
modx.pro
1
501
+20

Комментарии: 10

Алексей Соин
02 мая 2024, 12:07
0
а для чего таблицы chunks_time и templates_time?
    Василий Наумкин
    02 мая 2024, 12:11
    0
    Если же элемент не статичный, то из специальной таблички читается время его последнего обновления (которое сохряняется туда плагином, потому что MODX эти данные не хранит).
    Иначе обычные чанки будут компилироваться каждый раз и никакой пользы от кэширования. В pdoTools сейчас так и есть, между прочим.
    Артур Шевченко
    02 мая 2024, 12:15
    +1
    воротите, что хотите. Вплоть до удаления исходников сайта, это уже на ваше усмотрение.
    Это определённо очень важная возможность 😊
      Андрей Степаненко
      06 мая 2024, 22:57
      0
      php 7.4 не установился

      пробывал с:
      wget raw.githubusercontent.com/modxcms/revolution/v3.0.4-pl/composer.json
      wget raw.githubusercontent.com/modxcms/revolution/v3.0.5-pl/composer.json

      composer require mmx/fenom
      ./composer.json has been updated
      Running composer update mmx/fenom
      Loading composer repositories with package information
      Updating dependencies
      Your requirements could not be resolved to an installable set of packages.
      
        Problem 1
          - illuminate/container[v8.0.0, ..., 8.x-dev] require psr/container ^1.0 -> found psr/container[1.0.0, ..., 1.x-dev] but the package is fixed to 2.0.2 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
          - illuminate/events[v10.47.0, ..., 10.x-dev] require php ^8.1 -> your php version (7.4.33) does not satisfy that requirement.
          - mmx/database[1.1.0, ..., 1.2.0] require illuminate/events ^v8.83|^v10.47 -> satisfiable by illuminate/events[v8.83.0, ..., 8.x-dev, v10.47.0, ..., 10.x-dev].
          - mmx/fenom[dev-main, 1.0.0] require mmx/database ^1.1 -> satisfiable by mmx/database[1.1.0, 1.1.1, 1.2.0].
          - illuminate/events[v8.83.0, ..., 8.x-dev] require illuminate/container ^8.0 -> satisfiable by illuminate/container[v8.0.0, ..., 8.x-dev].
          - Root composer.json requires mmx/fenom * -> satisfiable by mmx/fenom[dev-main, 1.0.0, 9999999-dev].
      
      Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
      You can also try re-running composer require with an explicit version constraint, e.g. "composer require mmx/fenom:*" to figure out if any version is installable, or "composer require mmx/fenom:^2.1" if you know which you need.
      
      Installation failed, reverting ./composer.json and ./composer.lock to their original content.
      bash-5.1$ php -v
      PHP 7.4.33 (cli) (built: Nov 12 2022 05:16:49) ( NTS )
      Copyright © The PHP Group
      Zend Engine v3.4.0, Copyright © Zend Technologies
        Василий Наумкин
        07 мая 2024, 02:20
        0
        Тебе там пишут, что у тебя уже установлен пакет psr/container 2й версии. Проверяем, почему именно второй:

        Просто потому, что можно или 1ю, или 2ю. Никаких особых требований нет, поэтому Composer выбрал версию 2.

        Затем ты требуешь установить mmx/fenom — и тебе говорят, что для этого надо изменить зафиксированную версию psr/container.
        illuminate/container[v8.0.0, ..., 8.x-dev] require psr/container ^1.0 -> found psr/container[1.0.0, ..., 1.x-dev] but the package is fixed to 2.0.2 (lock file version)
        Как это сделать тебе говорят чуть ниже:
        Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
        Просто разреши даунгрейднуть версию ключом:
        composer require mmx/fenom -W

        Всё устанавливается, только что проверил на modhost.pro
        Андрей Степаненко
        06 мая 2024, 23:02
        0
        изначально делал так
        wget raw.githubusercontent.com/modxcms/revolution/v3.0.4-pl/composer.json
        composer install
        composer require mmx/fenom
        Получал ошибку modx.pro/development/24702#comment-143091

        Попробовал по другому
        Удалил composer.lock и core/vendor
        сразу выполнил команду
        composer require mmx/fenom

        все установилось

        Update:
        кроме самого пакета mmx/fenom (перепутал))) сначала подумал что он то же установился
        при повторе, опять ошибка не совместимости
        composer require mmx/fenom
        Андрей Степаненко
        07 мая 2024, 07:05
        0
        По тестировал, на modhost.pro
        попробуй вот так сделать:

        wget https://raw.githubusercontent.com/modxcms/revolution/v3.0.5-pl/composer.json
        composer install
        composer require mmx/fenom --update-no-dev
        будет ругаться на зависимости

        Удаление core/vendor и composer.lock обязателен получается.
        И затем установка
        wget https://raw.githubusercontent.com/modxcms/revolution/v3.0.5-pl/composer.json
        composer require mmx/fenom --update-no-dev

        Либо вариант, проблемы с зависимостями в ручную разруливать: modx.pro/development/24702#comment-143093
          Василий Наумкин
          07 мая 2024, 07:55
          +1
          Я же выше объяснил, что происходит.

          Ничего удалять не надо, просто добавляешь разрешение менять версии уже установленных пакетов ключом -W, что означает --with-all-dependencies.

          Это не ошибка, там нет никаких ошибок. Он просто не может разрешить зависимость автоматически и просит тебя указать ему явно разрешение:
          composer require mmx/fenom --update-no-dev --with-all-dependencies
          Алексей Шумаев
          07 мая 2024, 12:09
          +3
          После такого пинка по тушке modx у меня появилось желание наконец-то поставить 3 и что-то уже на нём сделать :-)
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            10