Как использовать параметр prepareSnippet
Для чего нужен и как использовать параметр prepareSnippet в пакете pdoTools.
Оглавление
Не так давно столкнулся с потребностью использовать функционал prepareSnippet
в своем проекте и с удивлением обнаружил, что в поиске Google и Yandex практически нет статей с хорошим разбором данного параметра. Для начала вникнем в его описание:
prepareSnippet — Указывает сниппет, который принимает данные перед выводом в чанк и может их менять или добавлять.
На самом деле это вполне четкое и понятное описание параметра, давайте посмотрим как его использовать на деле.
Создаем заготовку
Для примера я создал чистый сайт со следующей структурой:
Структура нужна для простоты примера. Далее в шаблоне я вывел обычным сниппетом pdoResources
все созданные ресурсы:
{'!pdoResources' | snippet : [
'parents' => 0,
'tpl' => '@INLINE <a href="{$uri}">{$pagetitle}</a><br>',
]}
Ну и конечно установил сам компонент pdoTools.
Получилась у меня небольшая навигация по сайту:
Как работает prepareSnippet
Параметр prepareSnippet принимает данные, которые отдает вызванный нами сниппет (в моем случае это pdoResources
). Но любой сниппет работающий через pdoTools, может работать с этим параметром, т. к. он является общим.
Мы можем получить, изменить и даже добавить данные перед их выводом. Но для этого нужно сделать два простых шага:
- Создать сниппет-обработчик (я его назвал
prepareSomething
) - В сниппете
pdoResources
в параметреprepareSnippet
указать его в качестве значения.
{'!pdoResources' | snippet : [
'parents' => 0,
'tpl' => '@INLINE <a href="{$uri}">{$pagetitle}</a><br>',
'prepareSnippet' => 'prepareSomething',
]}
Получаем данные
Для начала нам нужно посмотреть с чем мы можем работать. Все данные что нам нужны, лежат в массиве $row
. В созданном сниппете prepareSomething
пишем следующий код:
<?php
$modx->log(1, print_r($row, true));
После этого обновляем страницу и видим в логах массив данных по каждому объекту (в нашем случае, по каждому ресурсу):
(ERROR @ /home/blablabla/public_html/core/cache/includes/elements/modsnippet/11.include.cache.php : 2) Array
(
[prepareSnippet] => prepareSomething
[id] => 2
[type] => document
[contentType] => text/html
[pagetitle] => О нас
[longtitle] =>
[description] =>
[alias] => o-nas
[alias_visible] => 1
[link_attributes] =>
[published] => 1
[pub_date] => 0
[unpub_date] => 0
[parent] => 0
[isfolder] => 0
[introtext] =>
[richtext] => 1
[template] => 1
[menuindex] => 1
[searchable] => 1
[cacheable] => 1
[createdby] => 1
[createdon] => 1586801539
[editedby] => 1
[editedon] => 1586801837
[deleted] => 0
[deletedon] => 0
[deletedby] => 0
[publishedon] => 1586801520
[publishedby] => 1
[menutitle] =>
[donthit] => 0
[privateweb] => 0
[privatemgr] => 0
[content_dispo] => 0
[hidemenu] => 0
[class_key] => modDocument
[context_key] => web
[content_type] => 1
[uri] => o-nas
[uri_override] => 0
[hide_children_in_tree] => 0
[show_in_tree] => 1
[properties] =>
[idx] => 1
[link] =>
)
...
Я думаю вы уже поняли что все это — стандартные поля ресурса. Давайте добавим ресурсу какое-нибудь TV поле и запишем туда любое значение:
Однако же, если вы сейчас обновите страницу, то в массиве данных это поле вы не найдете. Потому что нужно включить данное TV поле в выборку с помощью параметра includeTVs
:
{'!pdoResources' | snippet : [
'parents' => 0,
'includeTVs' => 'myFirstTV',
'prepareSnippet' => 'prepareSomething',
'tpl' => '@INLINE <a href="{$uri}">{$pagetitle}</a><br>',
]}
Результат:
...
[uri] => o-nas
[tv.myFirstTV] => Мы самая крутая фирма по производству сайтов на MODx!
[idx] => 1
[link] =>
)
Изменяем данные
Мы научились получать данные, теперь давайте обработаем их через наш сниппет-обработчик и отдадим в шаблонизатор уже изменённые данные. Для этого идем в сниппет и пишем что-нибудь вроде этого:
<?php
$pagetitle = $row['pagetitle'];
$myFirstTV = $row['tv.myFirstTV'];
// Изменяем данные
$row['pagetitle'] = 'Страница - ' . $pagetitle;
$row['myFirstTV'] = $myFirstTV . ' и не только!';
// Если хотите посмотреть на новые плейсхолдеры в массиве
$modx->log(1, print_r($row, true));
// Возвращаем сериализованный массив.
return serialize($row);
Как видно, prepareSnippet должен возвращать результат работы в виде сериализованного массива данных.
Это полезно для хранения или передачи значений PHP между скриптами без потери их типа и структуры.
Теперь мы можем использовать измененные плейсхолдеры:
{'!pdoResources' | snippet : [
'parents' => 0,
'includeTVs' => 'myFirstTV',
'prepareSnippet' => 'prepareSomething',
'tpl' => '@INLINE <a href="{$uri}">{$pagetitle}</a><br>{$myFirstTV}<br><br>',
]}
Результат:
При этом, нам так же как и раньше доступен плейсхолдер с префиксом tv.
— {$_pls['tv.myFirstTV']}
{'!pdoResources' | snippet : [
'parents' => 0,
'includeTVs' => 'myFirstTV',
'prepareSnippet' => 'prepareSomething',
'tpl' => '@INLINE <a href="{$uri}">{$pagetitle}</a><br>{$_pls["tv.myFirstTV"]}<br><br>',
]}
Добавляем данные
Фактически мы уже это сделали в предыдущем шаге. Но там мы получали данные и изменяли их, перезаписывая, но мы можем создавать новые плейсхолдеры и в них помещать нужную нам информацию:
<?php
$pagetitle = $row['pagetitle'];
// Добавляем данные
$row['preparedPagetitle'] = 'Страница - ' . $pagetitle;
$row['randomNewValue'] = 'Генерим рандомное число - ' . rand(1, 500);
return serialize($row);
Теперь нам доступны два новых плейсхолдера — {$preparedPagetitle}
и {$randomNewValue}
. Давайте используем их:
{'!pdoResources' | snippet : [
'parents' => 0,
'includeTVs' => 'myFirstTV',
'prepareSnippet' => 'prepareSomething',
'tpl' => '@INLINE <a href="{$uri}">{$preparedPagetitle}</a><br>{$randomNewValue}<br><br>',
]}
В этом случае прежний плейсхолдер {$pagetitle}
будет доступен без внесенных нами изменений, а новый плейсхолдер {$preparedPagetitle}
выведет измененный результат. В свою очередь плейсхолдер {$randomNewValue}
выведет результат работы функции rand
.
Результат:
Эпилог
Как вы уже могли понять, в сниппете-обработчике можно проводить любые махинации с данными. Вы можете вызывать внутри этого сниппета — другой сниппет, подготавливать в нем миниатюры или прописывать любую другую логику на языке программирования PHP и выводить нужные вам данные в новых плейсхолдерах, либо изменять уже существующие.
Но не забывайте, что ваши скрипты в сниппете-обработчике будут отрабатывать для каждой итерации главного сниппета. При большом количестве данных или неоптимизированном PHP коде, это может сказаться на скорости рендера страниц вашего сайта.
Время запросов: 0,1176 s
Количество запросов: 28
Источник: cache