В CMF MODX Revolution сниппет (snippet) — это фрагмент PHP-кода, который может быть вызван в полях ресурса, чанке, шаблоне или другом сниппете для выполнения определенной функции.

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

Создание сниппета

Вызовите контекстное меню в дереве элементов во вкладке «Сниппеты». Можно воспользоваться кнопкой «Новый» — тогда откроется новая страницы. «Быстро создать» — появится форма во всплывающем окне.

Создание сниппета в MODX Revolution через контекстное меню в дереве элементов
Также можно использовать кнопки в дереве ресурсов.

Создание сниппета в MODX Revolution через кнопки создания в дереве элементов

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

Создание сниппета в MODX Revolution в модальном окне tagElementPlugin

Чтобы не путаться в нейминге, можно использовать php в начале названия — так сразу будет понятно, что вызываете именно сниппет. Еще упрощает жизнь создание структуры, наподобие объектной модели, например:

php.Article.GetTags
php.Article.UpdateHitsCount
php.Article.GetRating
php.Article.Articles.GetPopular
php.Tags.GetList
php.Author.GetRating

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

Использование

Сниппет всегда должен возвращать какое-то значение в return. Если фактически он возвращает пустое значение — можно вернуть true.

Например, вы создали сниппет php.snippetName и написали код, который отображает текущую дату и время.

return date("F j, Y, g:i a");

Вы можете вызвать его на странице или в шаблоне с помощью следующего тега:

[[php.snippetName]]

Когда страница будет отображена, результат будет вставлен в место расположения тега, если скрипт возвращает результат.

Бывают случаи, когда скрипт не возвращает результат сам по себе, а записывает его в плейсхолдеры — тогда сначала нужно вызвать сниппет, а затем указать плейсхолдер в месте, где нужно вывести результат. Зададим плейсхолдер date:

$modx->setPlaceholder('date', date("F j, Y, g:i a"));

А затем вызовем его на странице:

[[php.snippetName]]
<p>Текущая дата: [[+date]]</p>

Кеширование

Сниппеты могут вызываться в кешированном и некешированном виде.

<!-- кэшируемый -->
[[php.snippetName]]
<!-- некэшируемый -->
[[!php.snippetName]]

Кешируемый при первой генерации сохраняется в статичный файл, и при последующих обращениях будет браться именно из файла, чтобы сократить время на выполнения скриптов и нагрузку на базу данных. До тех пор, пока не будет очищен кеш — при сохранении сниппета или чисте кеша сайта, например.

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

Правило простое — используем кешируемые везде, где можно. Некешируемые вызываем только когда постоянно нужны актуальные данные или выполнение действия в момент загрузки страницы (получить get параметры; увеличить счетчик просмотров страницы и тд).

Также некешируемый вызов можно использовать на этапе разработки сайта, чтобы не пропускать ошибки, но не забудьте потом везде включить кеш.

Модификаторы

Сниппет можно использовать как модификатор вывода. Если кратко — мы можем добавить модификатор к тегу (чанку или полю ресурса, например), и этот модификатор поменяет значение этого тега при выводе.

В MODX есть встроенные модификаторы и фильтры, но если мы хотим создать свой — используем сниппеты. Например, создадим скрипт phpH1, который выведет pagetitle страницы в теге h1:

$input = $modx->getOption('input', $scriptProperties, '');
$output = $input;

if ($output != '') {
	$output = '<h1>' . $output . '</h1>';
}

return $output;

И используем его в шаблоне:

[[*pagetitle:phpH1]]

xPDO и MODX API

С помощью MODX API можно получать поля и TV поля текущего ресурса:

// значение поля
$pagetitle = $modx->resource->get('pagetitle');
// значение tv по имени tv
$tvValue = $modx->resource->getTVValue('tvName');
// значение tv по id tv
$tvValue = $modx->resource->getTVValue(1);

Или другого ресурса по его ID:

$res = $modx->getObject('modResource', 1);
$tvValue = $res->getTVValue('tvName');

Также мы можем строить продвинутые запросы xPDO. К примеру, получить ресурсы с шаблоном id=2, и вывести их заголовки на странице:

$q = $modx->newQuery('modResource');
$q->where(array(
	'template' => '2'
));
$q->select(array(
	'id', 
	'pagetitle'
));
$res = $modx->getCollection('modResource', $q);
foreach ($res as $r) {
	echo $r->get('pagetitle');
}

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

Вызов чанка

Основной грамотной разработки на PHP и в MODX в частности является разделение логики и представления. Проще говоря — надо разделять PHP код и верстку. Как Вы наверное уже знаете, для верстки в MODX используются чанки. Получить чанк в сниппете можно таким образом:

$html = $modx->getChunk('tplSomeChunk', 
	array(
		'placeholderName' => 'Oleg', 
		'placeholderAge' => 23
	)
);

В 1 параметре указывается название чанка, во втором — массив данных, которые могут быть использованы как плейсхолдеры в самом чанке, условно:

<p>Привет, я [[+placeholderName]], мне [[+placeholderAge]] года</p>

Когда мы получаем какие-то данные из базы данных, как правило каждая строка (если получаем ресурсы - то строка равна ресурсу), представлена как раз в виде массива данных:

[
	0 => [
		'id' => 1,
		'pagetitle' => 'value',
		...
	],
	1 => [
		'id' => 2,
		'pagetitle' => 'value2',
		...
	]
]

Поэтому мы можем передавать в вызов чанка прямо этот массив данных. В этом примере мы получаем ресурсы методом getCollection:

$output = '';

$q = $modx->newQuery('modResource');
$q->select(array(
    'id',
    'pagetitle'
));
$resources = $modx->getCollection('modResource', $q);

if ($resources) {  
    foreach ($resources as $res) {
        $resArr = $resources->toArray(); // Приводим объект в обычный массив
        $output .= $modx->getChunk('tplSomeChunk', $resArr);
    }
}

return $output;

Как видите, чтобы передать ресурс в качестве аргумента, сначала нужно привести его из объекта в массив. Если же получать не объекты, а сразу массив данных — такая манипуляция не нужна:

$output = '';

$q = $modx->newQuery('modResource');
$q->select(array(
	'id', 
	'pagetitle'
));

$q->prepare();
$q->stmt->execute();
$resources = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
if ($resources) {
	foreach ($resources as $resource) {
		$output = $modx->getChunk('tplSomeChunk', $resource);
	}
}

return $output;

Передача параметров

Сниппеты также могут принимать входные параметры. Это позволяет настроить различные сценарии поведения скрипта.

Чтобы передать параметры, используйте следующий синтаксис:

[[snippetName?
	&parameter1=`value1`
	&parameter2=`[[*pagetitle]]`
	&parameter3=`[[php.My.Snippet]]`
	&parameter4=`[[+placeholder]]`
	&parameter4=`[[++systemVar]]`
]]

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

Внутри кода получить доступ к значениям параметров можно с помощью метода $modx->getOption(). При этом можно задать значение по умолчанию. Например:

$parameter1 = $modx->getOption('parameter1', $scriptProperties);
// Задать значение по умолчанию
$parameter2 = $modx->getOption('parameter2', $scriptProperties, 'Привет');

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