Создание пользовательского сниппета


Шаблонизация сниппетов в MODx Revolution

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

Наш начальный сниппет

Давайте разберём пример, где вам нужно пройти через опубликованные неудалённые ресурсы, которые являются наследниками Ресурса с ID 390, отсортированного по и далее вывести их в тегах LI с именем статьи pagetitle и активной ссылкой.

Давайте продолжим и создадим сниппет с именем 'ResourceLister' и вставим следующий код:

/* первое, постройте запрос */
$c = $modx->newQuery('modResource');
/* нам нужны только опубликованные и неудалённые ресурсы */
$c->where(array(
  'published' => true,
  'deleted' => false,
));
/* взять все наследники ресурса с ID 390 */
$children = $modx->getChildIds(390);
if (count($children) > 0) {
    $c->where(array(
        'id:IN' => $children,
    ));
}
/* отсортировать новые сверху */
$c->sortby('menuindex','ASC');
/* взять ресурсы как xPDOObjects */
$resources = $modx->getCollection('modResource',$c);
 
$output = '';
foreach ($resources as $resource) {
   $output .= '
  • '.$resource->get('pagetitle').'
  • '; } return $output;

    Это делает то, что нам нужно, но содержит внутри HTML код. Нас такое не устраивает. Это не даёт пользователю возможность контролировать разметку или менять её, если он это захочет сделать. Нам нужно больше гибкости.

    Шаблонизация сниппета

    Во-первых, давайте создадим чанк, который мы будем использовать для каждого элемента в результирующем выводе. Назовём его "ResourceItem" и код содержимого назначим как:

    В основном, мы пользуемся тегами LI и помещаем несколько заполнителей туда, где находился наш контент. Мы имеет доступ к каждому полю в ресурсе и теперь мы просто используем ID и поле ресурса pagetitle. Выражение [[~ говорит MODx, чтобы сделал ссылку от ID переданного через [[+id]] параметр. Давайте добавим параметр по-умолчанию к сниппету, называемый 'tpl' к верху нашего сниппет кода:

    $tpl = $modx->getOption('tpl',$scriptProperties,'ResourceItem');
    
    

    Этим мы получим в распоряжение параметр &tpl= от вызова Сниппета  поскольку $scriptProperties просто содержит все параметры в вызове Сниппета. Если 'tpl' не существует, то по-умолчанию getOption является значением ResourceItem (чанк, который мы создали недавно).

    После этого мы меняем цикл по каждому элементу в Сниппете на такой:

    foreach ($resources as $resource) {
       $resourceArray = $resource->toArray();
       $output .= $modx->getChunk($tpl,$resourceArray);
    }

    Код вначале возвращает объект modResource в массив пар field=name (например, $resourceArray ['pagetitle'] - это pagetitle) используя метод toArray(). Далее мы используем $modx->getChunk() для передачи нашего tpl чанка и массива ресурсов в него как параметры. MODx парсит чанк, заменяет параметры и возвращает нам некоторый контент.

    Теперь пользователь может вызывать сниппет этим способом для перезаписи чанка для каждого ресурса с помощью такого вызова:

    
    
    

    Это значит, что пользователи могут шаблонизировать их результаты вызова как им угодно – используя теги Lis или поля таблиц, в общем что угодно! Вы создали гибкий и мощный сниппет!

    Добавление класса для Ряда

    Если мы хотим, чтобы пользователи могли определять CSS класс для каждого LI ряда, но не могли делать свои собственные чанки. Тогда мы просто добавляем параметр по-умолчанию 'rowCls' для кода нашего сниппета вверху прямо под нашим первым вызовом getOption:

    $rowCls = $modx->getOption('rowCls',$scriptProperties,'resource-item');
    

    Это говорит MODx, что по-умолчанию &rowCls класс ряда для сниппета - это 'resource-item'. Давайте отредактируем наш чанк ResourceItem:

    И далее изменим наш цикл для каждого элемента:

    foreach ($resources as $resource) {
       $resourceArray = $resource->toArray();
       $resourceArray['rowCls'] = $rowCls;
       $output .= $modx->getChunk($tpl,$resourceArray);
    }
    
    

    Обратите внимание как мы в прямой форме определили переменную 'rowCls' в наш массив параметров $resourceArray. Мы так сделали, потому что у нас уже есть значение rowCls ранее в этом сниппете (с вызовом getOption) и теперь мы знаем, что он не будет отличаться для каждого ряда.

    Передача пользовательского ID

    Если мы хотим, чтобы пользователь имел возможность передавать от какого предка брать ресурсы. Тогда мы просто добавляем параметр 'id' к коду нашего сниппета вверху под вызовом getOption:

    $id = (int)$modx->getOption('id',$scriptProperties,390);

    В основном позволять пользователям переписывать (назначать) родительский ID для Сниппета – для примера скажем Ресурс 123 с параметром &id=`123` - в их вызове сниппета. Мы хотим, чтобы по умолчанию он равнялся 390. И далее мы поменяем строку getChildIds для этого:

    $children = $modx->getChildIds($id);

    Очевидно, что вы могли бы добавить больше функций к этому сниппету, таким как firstRowCls (для первого ряда результата вызова), lastRowCls, firstRowTpl, sortBy, sortDir, limit и всё угодно, что вы смогли бы придумать. Мы могли бы даже сделать фильтр 'published' как параметр или скрывать ресурсы, которые являются папками для других ресурсов и др. Теперь важно, что вы имеете общее представление о создании пользовательского сниппета.

    Для справки, наш конечный код выглядит вот так:

    
    $tpl = $modx->getOption('tpl',$scriptProperties,'ResourceItem');
    $id = (int)$modx->getOption('id',$scriptProperties,390);
    $rowCls = $modx->getOption('rowCls',$scriptProperties,'resource-item');
     
    $c = $modx->newQuery('modResource');
    $c->where(array(
      'published' => true,
      'deleted' => false,
    ));
    $children = $modx->getChildIds($id);
    if (count($children) > 0) {
        $c->where(array(
            'id:IN' => $children,
        ));
    }
    $c->sortby('menuindex','ASC');
    $resources = $modx->getCollection('modResource',$c);
     
    $output = '';
    foreach ($resources as $resource) {
        $resourceArray = $resource->toArray();
        $resourceArray['cls'] = $rowCls;
        $output .= $modx->getChunk($tpl,$resourceArray);
    }
    return $output;
    
    
    Оригинал статьи