Дата публикации
13 Апреля 2020
Дата изменения
5 Июля 2020
Уникальных просмотров
1.175

Оглавление

Не так давно столкнулся с потребностью использовать функционал prepareSnippet в своем проекте и с удивлением обнаружил, что в поиске Google и Yandex практически нет статей с хорошим разбором данного параметра. Для начала вникнем в его описание:

prepareSnippet — Указывает сниппет, который принимает данные перед выводом в чанк и может их менять или добавлять.

На самом деле это вполне четкое и понятное описание параметра, давайте посмотрим как его использовать на деле.

Создаем заготовку

Для примера я создал чистый сайт со следующей структурой:

Структура сайта для примера

Структура нужна для простоты примера. Далее в шаблоне я вывел обычным сниппетом pdoResources все созданные ресурсы:

{'!pdoResources' | snippet : [
'parents' => 0,
'tpl' => '@INLINE <a href="{$uri}">{$pagetitle}</a><br>',
]}

Ну и конечно установил сам компонент pdoTools.

Получилась у меня небольшая навигация по сайту:

Результат заготовки

Как работает prepareSnippet 

Параметр prepareSnippet принимает данные, которые отдает вызванный нами сниппет (в моем случае это pdoResources). Но любой сниппет работающий через pdoTools, может работать с этим параметром, т. к. он является общим.

Мы можем получить, изменить и даже добавить данные перед их выводом. Но для этого нужно сделать два простых шага:

  1. Создать сниппет-обработчик (я его назвал prepareSomething)
  2. В сниппете 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 поле

Однако же, если вы сейчас обновите страницу, то в массиве данных это поле вы не найдете. Потому что нужно включить данное 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>',
]}

Результат:

Результат работы параметра prepareSnippet

При этом, нам так же как и раньше доступен плейсхолдер с префиксом 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.

Результат:

Результат работы параметра prepareSnippet

Эпилог

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

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

Благодарность автору

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

Один из самых популярных способов поблагодарить автора, воспользоваться сервисом Яндекс.Деньги.

Время работы: 0,1176 s
Время запросов: 0,1176 s
Количество запросов: 28
Источник: cache