Jump to main content Jump to doc navigation

Что такое сниппет

Сниппеты — это способ запускать динамический PHP внутри страниц.

Сниппет — короткий переиспользуемый кусок PHP, который возвращает значение. Чанк возвращает статическую разметку с плейсхолдерами, а сниппет вычисляет вывод в момент отрисовки.

Как выполняются сниппеты

Кэшируемый сниппет компилируется в обычный include-файл в cache/includes/elements/modsnippet/ и выполняется через include. Тело не оборачивается в функцию — нет ни eval(), ни сгенерированной функции, поэтому внутри сниппета не существует $this, а $modx — единственный объект в области видимости.

Кэшируемость определяется тегом, а не свойством: [[mySnippet]] кэшируется, [[!mySnippet]] — нет. Колонка cache_type у сниппетов объявлена устаревшей и никогда не читается.

После выполнения вывод разбирается парсером MODX, поэтому в нём могут быть теги элементов.

Простой пример

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

<?php
return 'Привет, мир!';

Если вы назвали этот сниппет “helloWorld”, вы можете вызвать его, используя [[helloWorld]] в ваших документах, шаблонах или чанках (см. Синтаксис тегов). Вы также можете вызвать сниппет из другого сниппета, используя метод API runSnippet.

Возврат значения — соглашение. echo тоже работает: MODX запускает буфер вывода перед подключением файла и приклеивает напечатанное к возвращённому значению, но return держит вывод в одном месте.

Передача значений в сниппет

Значения передаются в нотации типа CGI, которая следует за именем сниппета. Для сниппета mySnippet:

[[!mySnippet? &input=`Привет, мир`]]

И код вашего сниппета может выглядеть примерно так:

<?php
return 'Мой ввод был: ' . $input;
?>

Имена параметров в вызове должны точно совпадать с переменными в сниппете, с учётом регистра: input, а не INPUT. Не забывайте & перед именами и обратные кавычки вокруг значений.

Чтение значений

Аргументы приходят переменными с тем же именем: &someParameter в вызове становится $someParameter в коде PHP.

Весь массив доступен как $scriptProperties — удобно, когда имена заранее неизвестны.

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

[[!mySnippet? &x=`x-ray` &y=`yellow`]]

Тогда массив $scriptProperties будет содержать следующее:

Array(
 'x' => 'x-ray',
 'y' => 'yellow'
)

Записи вкладки Properties и набор свойств из [[mySnippet@setName]] подставляются первыми, а параметры вызова переопределяют их по ключу.

Взаимодействие с базой данных в сниппетах

MODX ходит в базу через xPDO — ORM поверх PDO. Берите данные через getObject и getCollection, а не пишите сырые запросы.

Почему ORM?

  1. Абстракция SQL — один и тот же код работает на MySQL, SQLite и PostgreSQL.
  2. Экранирование параметров — xPDO передаёт значения через PDO, пути для SQL-инъекции нет.
  3. Короткий код — работа на 40 строк с вызовами mysql_* сжимается примерно до десяти.

Пример кода БД

Возьмём чанк с названием LineItem и заменим его плейсхолдеры [[+placeholderName]] значениями:

$chunk = $modx->getObject('modChunk',array(
   'name' => 'LineItem',
));
if (!$chunk) return 'Нет такого чанка с названием LineItem!';
return $chunk->process(array(
   'name' => 'G.I. Joe',
   'grenades' => 42,
));

$chunk — это xPDOObject, объектное представление чанка с уже обработанными плейсхолдерами.

Для настоящих запросов используйте $modx->newQuery() — здесь так берутся первые 10 опубликованных ресурсов с родителями 23, 24 или 25, отсортированные по menuindex:

$c = $modx->newQuery('modResource');
$c->where(array(
   'parent:IN' => array(23,24,25),
   'deleted' => false,
   'hidemenu' => false,
   'published' => true,
));
$c->sortby('menuindex','ASC');
$c->limit(10);
$resources = $modx->getCollection('modResource',$c);

newQuery() принимает имя класса, where() добавляет ограничения, затем sortby() и limit() оформляют результат.

getCollection() возвращает массив объектов, а getObject() — один объект.

Дальнейшие подробности о работе с базой данных

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

Разработка сниппетов вне менеджера

Направьте статический сниппет на файл на диске вместо вставки кода в менеджер:

[[!include? &file=`/absolute/path/to/my/snippet.php`]]

Тело самого сниппета остаётся тонким:

if (file_exists($file)) {
   $o = include $file;
} else { $o = 'Файл не найден по адресу: '.$file; }
return $o;

Так файл можно проверять линтером из командной строки (php -l my_script.php) и получать настоящие сообщения об ошибках. Переносите код в менеджер только после того, как он заработает.

[!WARNING] PHP-файл внутри веб-корня доступен любому. Вынесите файлы сниппетов за пределы веб-корня или перенесите туда каталог core/ до деплоя. Проверка «я внутри MODX» внутри файла слабее, чем его перенос.

Не смешивайте PHP и HTML в сниппете

Сниппеты выполняют PHP-код, поэтому код сниппета сам по себе должен быть корректным PHP. Код ниже — нет:

<p>Это ужасная смесь HTML и PHP кода</p>
<?php
return "<p>и PHP!  Не пытайтесь делать так! Это плохая архитектура и не сработает!</p>";
?>

MODX дописывает ровно один <?php в начало кода перед записью в кэш, поэтому исполняемый файл начинается с <?php, за которым идёт посторонний HTML. Это синтаксическая ошибка, а не пара <?php … ?>, которую утверждали прежние версии этой страницы.

Если вам нужно сделать что-то вроде этого, используйте чанк - выделите PHP в сниппет, загрузите его вывод в плейсхолдер с помощью функций-плейсхолдеров MODX API или обработайте сниппетом, и включите плейсхолдеры сниппета в чанк:

$output = $modx->getChunk('myChunk',array(
  'placeholderOne' => 'test',
  'name' => 'Harry',
  'scar' => 'Lightning',
));
return $output;

Не работайте с боевыми сниппетами

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

Используйте свойства по умолчанию

Попробуйте добавить свойства по умолчанию для вашего сниппета на вкладку «Свойства», чтобы другой разработчик мог добавить пользовательские наборы свойств для их переопределения.

Смотрите также

Support the team building MODX with a monthly donation.

The budget raised through OpenCollective is transparent, including payouts, and any contributor can apply to be paid for their work on MODX.

Backers

  • modmore
  • STERC
  • Digital Penguin
  • Jens Wittmann – Gestaltung & Entwicklung
  • CrewMark
  • Fabian Christen
  • Sepia River Studios
  • Dannevang Digital
  • A. Moreno
  • Alex
  • Chris Fickling
  • Stéphane Jäggi
  • Murray Wood
  • JT Skaggs
  • Anton Tarasov
  • deJaya
  • Lefthandmedia
  • eydolan
  • Following Sea
  • Guido Gallenkamp
  • YJ
  • Raffy
  • Snow Creative
  • Nick Clark
  • Guest
  • Helen
  • krisznet
  • Yanni
  • Richard

Budget

$194 per month—let's make that $500!

Learn more