Представляю законченное решение для работы с файловыми элементами, собранное в пакет. Это расширение pdoTools, которое добавляет в него модификаторы chunk, snippet, template и code. Из этого следует, что pdoTools должен быть уже установлен. Синтаксис точно такой же, как и в pdoTools — в названии элементов можно вставлять префиксы @FILE, @INLINE, @CODE и т.д. Поэтому вызовы элементов, описанные в прошлых статьях, теперь немного изменились.

Инструкция

Устанавливаем пакет. Затем в системной настройке pdoTools.class нужно указать новый класс «pdotools.pdotoolsplus».

По-умолчанию, путь к файлам элементов core/elements/(chunks|snippets|plugins|templates). Но его можно переопределить с помощью параметра «tplPath».

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

Чанки

  • Получаем MODX чанк «head».
    {'head' | chunk}
  • Получаем чанк из файла core/elements/chunks/head.tpl.
    {'@FILE head.tpl' | chunk}
  • Получаем чанк из файла assets/tpl/main/head.tpl.
    {'@FILE head.tpl' | chunk : ['tplPath'=>'assets/tpl/main/']}
  • Получаем чанк из файла assets/tpl/main/head.tpl.
    {'@FILE main/head.tpl' | chunk : ['tplPath'=>'assets/tpl/']}
  • Получаем inline чанк.
    {'@INLINE <p>This is an inline chunk </p>' | chunk}
  • Передаем плейсхолдеры в чанк.
    {'@INLINE <p>The value of the placeholder pls is [[+pls]]</p>' | chunk : ['pls'=>'some value'].}
  • Загружаем MODX шаблон «Bootstrap.Main».
    {'@TEMPLATE Bootstrap.Main' | chunk}

Данные теги указываются в чанках, шаблонах и ресурсах. Для чанков разрешены расширения 'html' и 'tpl'.

Сниппеты

  • Загружает MODX сниппет «mySnippet».
    {'mySnippet' | snippet}
  • Передаём параметры в сниппет.
    {'mySnippet' | snippet : ['tpl'=>'myTplChunk', 'parent'=>$_modx->resource.id]}
  • Загружает сниппет из файла core/elements/snippets/mysnippet.php.
    {'@FILE mysnippet' | snippet}
  • Загружает сниппет из файла assets/snippets/products/head.tpl.
    {'@FILE mysnippet' | snippet : ['tplPath'=>'assets/snippets/products/']}
  • Загружает сниппет из файла assets/snippets/products/head.tpl.
    {'@FILE products/mysnippet' | snippet : ['tplPath'=>'assets/snippets/products/']}
  • Передаем массив параметров $scriptProperties в сниппет.
    {'@FILE mysnippet' | snippet : ['var1'=>'val1', 'var2'=>'val2']}
  • Передаём параметр в inline сниппет. Также можно использовать префикс @INLINE.
    {'@CODE return "This resource created on " . date("m.d.Y", strtotime($createdon));' | snippet : ['createdon'=>'[[*createdon]]']}
  • Используется модификатор code.
    {'return "This resource created on " . date("m.d.Y", strtotime($createdon));' | code : ['createdon'=>'[[*createdon]]']}

Важно!

Inline сниппеты доступны, если обе системные настройки «pdotools_fenom_modx» и «pdotools_fenom_php» включены.

Указанные выше примеры используются в чанках, шаблонах и ресурсах. В PHP коде для загрузки кода из файла вы можете использовать метод pdoTools::runSnippet(). Он поддерживает префикс @FILE в названии сниппета. Если префикс не указан, то pdoTools запускает метод $modx->runSnippet().

$pdoTools = $modx->getService('pdoTools');
// будет запущен метод modX::runSnippet('mySnippet', $arrayOfProperties).
$result = $pdoTools->runSnippet('mySnippet', $arrayOfProperties); 
// pdoTools загрузит файл core/elements/snippets/mysnippet.php.
$result = $pdoTools->runSnippet('@FILE mysnippet', $arrayOfProperties); 

Чтобы изменить путь к файлу, в массиве параметров нужно в ключе «tplPath» передать новый путь.

Шаблоны

Способов может быть несколько. Рассмотрим парочку. В первом случае вы создаёте столько шаблонов, сколько вам нужно. И в каждом шаблоне указываете тег фенома.

  • Загрузка MODX шаблона «Bootstrap.Main».
    {'@TEMPLATE Bootstrap.Main' | chunk}
  • Тоже самое с использованием модификатора template.
    {'Bootstrap.Main' | template}
  • Загрузка шаблона из файла core/elements/templates/mainpage.html
    {'@FILE mainpage.html' | template}

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

Второй способ — это перенести всю логику в файл сниппета, который вызывается в шаблоне. И этот шаблон указывается для всех ресурсов.

{@FILE 'gettemplate' | snippet : ['resource'=>$_modx->resource]} — передаём массив с данными ресурса в сниппет.

Код сниппета может быть таким:

<?php  
$output = '';  
switch (true) {  
    // Определяем шаблон для единичных ресурсов
    case ($resource['id'] == 1): // Проверяем id документа  
        $output = $pdoTools->getChunk('@FILE main.html', array('tplPath'=>'core/elements/templates'));  
        break;  
    case ($resource['id'] == 7):
        $output = $pdoTools->getChunk('@FILE contacts.html, array('tplPath'=>'core/elements/templates')');
        break;
    // Определяем шаблон для группы ресурсов. 
    // Если ресурс переместить в другого родителя, то шаблон поменяется автоматически в соответствии с условием.
    case in_array($resource['parent'], array(2,3)): 
        $output = $pdoTools->getChunk('@FILE services.html, array('tplPath'=>'core/elements/templates')');
        break;
    case in_array($resource['parent'], array(4,5)): 
        $output = $pdoTools->getChunk('@FILE news.html, array('tplPath'=>'core/elements/templates')');
        break;        
    default:
        $output = $resource['content']; // Пустой шаблон - только контент страницы.
        break;
}
return $output;

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

Плагины

Сначала в папке core/elements/plugin/ создадим файл myplugin.php:

<?php
// 1. Перечисляем в массиве необходимые события(для примера, "OnWebPagePrerender")  
$events = array('OnWebPagePrerender');

// Две следующие строчки обязательны!
$pdoTools = $modx->getService('pdoTools');
if (!$pdoTools->initPlugin($this, $events, false)) return; // Третий параметр отвечает за отключение плагина: true - отключает.

// 2. Ваш код для указанных событий
switch ($modx->event->name) {
    case 'OnWebPagePrerender':
        /* Ваш код */
        break;
}

Теперь в админке MODX создадим плагин со следующим содержанием:

<?php
if (!empty($this->static_file) && file_exists($this->static_file)) include_once $this->static_file;

Отмечаем событие «OnMODXInit» и привязываем наш файл myplugin.php к плагину MODX. Для этого выполняем 4 действия:

  • Отмечаем чекбокс «Статичный файл».
  • В открывшемся поле выбираем наш файл или прописываем руками (core/elements/plugins/myplugin.php).
  • Убираем чекбокс «Статичный файл», чтобы MODX не синхронизировал файл с базой данных.
  • Сохраняем плагин.

На этом всё. На самом деле всё не так сложно как кажется с первого взгляда.

Преимущества данного решения

  • Все элементы хранятся на диске. Никаких элементов в базе данных. Никаких элементов в дереве элементов.
  • Изменения отражаются сразу же после сохранения файла.
  • MODX не удаляет кэш всего сайта после изменения элемента.
  • Получаем наслаждение от работы в любимом IDE редакторе.
  • Полноценный контроль версий.

Заключение

Важно знать, что такие элементы не кэшируются MODX. Поэтому, если у вас есть тяжёлые сниппеты или чанки, вам нужно самостоятельно позаботиться о кэшировании результатов. Для этого можно использовать методы setCache() и getCache() класса pdoTools или методы менеджера кэширования MODX modCacheManager.

Теперь вам не нужно так часто ходить в админку. Пробуйте. Это реально очень удобно.

Скачать пакет можно отсюда.

П.С. Вполне возможно, что такой функционал в скором времени появится в pdoTools. Но пока Василий занят другими делами, можно экспериментировать с этим решением.

14 мая 2016, 10:39   2310     6

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

  1. Павел Устюгофф 02 марта 2017, 15:42 # 0
    спасибо за полезную статью!
    я правильно понял, теперь весь этот функционал появился в Василия?
    1. Сергей Шлоков 02 марта 2017, 16:53 # 0
      Большая часть.
    2. Сергей 21 июля 2017, 16:51 # 0
      Подскажите пожалуйста вот такую конструкцию можно на fenom синтаксис переписать?
      [[pdoResources?
      &parents=`1`
      &tpl=`@INLINE [[+tv.сompanyAdr]]`
      &includeTVs=`сompanyAdr`
      ]]

      Ато я пробую пробую, но что то пока не получается (
      1. Сергей Шлоков 21 июля 2017, 22:07 # +1
        Как-то так
        {'pdoResources' | snippet : [
            'parents' => 1,
            'tpl'=>'@INLINE  {$_pls["tv.сompanyAdr"]}',
            'includeTVs'=>'сompanyAdr',
        ]}
        
      2. Сергей 22 июля 2017, 12:31 # 0
        Сергей, спасибо за быстрый ответ, ошибку свою понял)) ставил одинарные кавычки в квадратных скобках в место двойных…
        1. Сергей Шлоков 22 июля 2017, 18:53 # 0
          На здоровье! Можно и одинарные, но тогда их надо экранировать.

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

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