Библиотека pdoTools включает три основных класса для работы с базой данных и шаблонизацией в MODX Revolution. Каждый класс решает свои задачи, но все они объединены общей идеей — максимальная производительность и удобство разработки.
- pdoTools — основной класс библиотеки
- Инициализация класса
- Ведение лога работы
- Временное кеширование данных
- Постоянное кеширование через MODX
- Утилиты для работы с данными
- Метод makePlaceholders
- Метод buildTree
- Работа с чанками и шаблонизация
- Типы чанков
- Обработка плейсхолдеров
- Производительность шаблонизации
- Быстрые плейсхолдеры
- Быстрый режим обработки
- pdoFetch — класс для работы с базой данных
- Инициализация pdoFetch
- Создание запроса — метод makeQuery
- Работа с TV-параметрами
- Метод addTVFilters
- Метод addTVs
- JOIN операции — метод addJoins
- Типы присоединения таблиц
- Пример присоединения таблиц в PHP
- Пример в сниппете через JSON
- Группировка — метод addGrouping
- Выбор полей — метод addSelects
- Условия выборки — метод addWhere
- Фильтрация по TV-параметрам
- Чистый SQL в условиях
- Сортировка — метод addSort
- Выполнение запроса и возврат результатов
- Обработка результатов
- Методы getArray и getCollection
- pdoParser — быстрый парсер тегов MODX
- Обработка простых плейсхолдеров
- Теги FastField
- Шаблонизатор Fenom
- Возможности Fenom
- Системные настройки Fenom
- Порядок запуска шаблонизатора
- Кеширование чанков Fenom
- Пример использования Fenom
- Заключение
pdoTools — основной класс библиотеки
Базовый класс компонента, который наследуют все остальные сниппеты (кроме pdoParser, который расширяет modParser). Класс pdoTools предоставляет инструменты для логирования, кеширования и работы с чанками.
Инициализация класса
Простейший способ получить экземпляр pdoTools:
$pdoTools = $modx->getService('pdoTools');
Этот метод всегда возвращает оригинальный класс pdoTools. Если вы хотите использовать расширенную версию класса, указанную в системных настройках, инициализируйте его так:
$fqn = $modx->getOption('pdoTools.class', null, 'pdotools.pdotools', true);
if ($pdoClass = $modx->loadClass($fqn, '', false, true)) {
$pdoTools = new $pdoClass($modx, $scriptProperties);
}
elseif ($pdoClass = $modx->loadClass($fqn, MODX_CORE_PATH . 'components/pdotools/model/', false, true)) {
$pdoTools = new $pdoClass($modx, $scriptProperties);
}
else {
$modx->log(modX::LOG_LEVEL_ERROR, 'Could not load pdoTools');
return false;
}
$pdoTools->addTime('pdoTools loaded');
Такой способ инициализации используется во всех сниппетах pdoTools, что позволяет подменить функциональность своей версией класса.
Ведение лога работы
Важная особенность pdoTools — умение вести детальный лог своей работы. Для этого доступны методы:
addTime(string $message) — добавляет новую запись в лог с текущей меткой времени
getTime(bool $string = true) — возвращает итоговое время работы и либо отформатированную строку (по умолчанию), либо массив время => сообщение
Пример использования логирования:
$pdo = $modx->getService('pdoTools');
$pdo->addTime('pdoTools инициализирован');
print_r($pdo->getTime());
Результат вывода:
0.0000150: pdoTools инициализирован
0.0000272: Total time
1 572 864: Memory usage
Вы можете подключать pdoTools в своих сниппетах просто для логирования событий. Сниппеты pdoTools автоматически пишут всё в лог, и менеджер может его просмотреть через параметр &showLog=1.
Временное кеширование данных
pdoTools умеет кешировать произвольные данные на время выполнения скрипта. Методы для работы с временным хранилищем:
- setStore(string $name, mixed $object, string $type = ‘data’) — сохраняет любые данные во временное хранилище.
- getStore(string $name, string $type = ‘data’) — получает данные или возвращает null если они отсутствуют.
Пример кеширования пользователей для избежания повторных запросов:
foreach ($users as $id) {
$user = $pdo->getStore($id, 'user');
if ($user === null) {
if (!$user = $modx->getObject('modUser', $id)) {
$user = false;
}
$pdo->setStore($id, $user, 'user');
}
elseif ($user === false) {
echo 'Не могу найти юзера с id = ' . $id;
}
else {
echo $user->get('username');
}
}
В этом коде мы сохраняем пользователей в отдельный namespace user для изоляции от других сниппетов. Обратите внимание, что кеш может вернуть null (данные еще не получались) или false (данные не найдены). В любом случае, запрос в БД будет только один на каждого пользователя.
Сам pdoTools кеширует таким образом вызовы чанков. Данные сохраняются только на время работы скрипта и не записываются на жесткий диск.
Постоянное кеширование через MODX
Для более продвинутого кеширования с сохранением на диск используются методы:
- setCache(mixed $data, array $options) — сохраняет данные в кеш, генерируя ключ из параметров.
- getCache(array $options) — выдает закешированные данные согласно параметрам.
Пример использования постоянного кеша:
$pdo = $modx->getService('pdoTools');
$options = array(
'user' => $modx->user->get('id'),
'page' => @$_REQUEST['page'],
'cacheTime' => 10,
);
$pdo->addTime('pdoTools загружен');
if (!$data = $pdo->getCache($options)) {
$pdo->addTime('Кэш не найден, генерируем данные');
$data = array();
for ($i = 1; $i <= 100000; $i++) {
$data[] = rand();
}
$data = md5(implode($data));
$pdo->setCache($data, $options);
$pdo->addTime('Данные сохранены в кэш');
}
else {
$pdo->addTime('Данные загружены из кэша');
}
print_r($data);
Таким образом, в зависимости от пользователя и страницы генерируются и кешируются данные. При первом запуске лог покажет:
0.0000281: pdoTools загружен
0.0004001: No cached data for key "default/e713939a1827..."
0.0000079: Кэш не найден, генерируем данные
0.0581820: Saved data to cache "default/e713939a1827..."
0.0000181: Данные сохранены в кэш
0.0586412: Total time
1 835 008: Memory usage
При последующих запросах:
0.0000310: pdoTools загружен
0.0007479: Retrieved data from cache "default/e713939a1827..."
0.0000081: Данные загружены из кэша
0.0007918: Total time
1 572 864: Memory usage
pdoTools автоматически логирует работу с кешем, поэтому вам не нужно это делать вручную.
Утилиты для работы с данными
Метод makePlaceholders
Принимает массив данных и возвращает два массива для шаблонизации:
- makePlaceholders(array $data, string $plPrefix = », string $prefix = ‘[[+’, string $suffix = ‘]]’, bool $uncacheable = true)
Параметры метода:
$data— массив ключ => значение$plPrefix— префикс для плейсхолдеров$prefix— открывающие символы (по умолчанию[[+)$suffix— закрывающие символы (по умолчанию]])$uncacheable— генерировать ли некешированные плейсхолдеры
Пример использования:
$data = array(
'key1' => 'value1',
'key2' => 'value2',
);
$pls = $pdo->makePlaceholders($data);
print_r($pls);
Результат:
Array
(
[pl] => Array
(
[key1] => [[+key1]]
[!key1] => [[!+key1]]
[key2] => [[+key2]]
[!key2] => [[!+key2]]
)
[vl] => Array
(
[key1] => value1
[!key1] => value1
[key2] => value2
[!key2] => value2
)
)
Дальше можно обработать HTML шаблон:
$html = str_replace($pls['pl'], $pls['vl'], $html);
Метод buildTree
Строит иерархическое дерево из массива ресурсов, используется сниппетом pdoMenu:
$pdo = $modx->getService('pdoFetch');
$resources = $pdo->getCollection('modResource');
$tree = $pdo->buildTree($resources);
print_r($tree);
Метод вернет структурированное дерево ресурсов вашего сайта.
Работа с чанками и шаблонизация
Это наиболее интересная часть класса pdoTools. Основной метод — getChunk(), вся реализация которого нацелена на максимальную производительность и функциональность.
Типы чанков
getChunk умеет работать с разными типами чанков:
- @INLINE или @CODE — чанк создается из переданной строки
- @FILE — чанк получается из файла (только с расширениями .html и .tpl из директории
pdotools_elements_path) - @TEMPLATE — чанк создается из шаблона сайта (можно указывать ID или имя)
- @CHUNK или просто строка без @ — выборка обычного чанка из БД
Обработка плейсхолдеров
Все простые плейсхолдеры без условий и фильтров обрабатывает pdoParser:
[[%tag]]— строка лексикона[[~id]]— ссылка[[+tag]]— обычные плейсхолдеры[[++tag]]— системные плейсхолдеры[[*tag]]— плейсхолдеры ресурса
Производительность шаблонизации
Рабочий пример с измерением скорости:
$tpl = '@INLINE <p>[[+param]] - [[+value]]</p>';
$res = '';
for ($i = 1; $i <= 10000; $i++) {
$pls = array('param' => $i, 'value' => rand());
$res .= $pdo->getChunk($tpl, $pls);
}
print_r($pdo->getTime());
print_r($res);
Этот код выводит 10 000 строк всего за 0.17 секунды ! Неважно, что чанк @INLINE — обычный работает с той же скоростью. Если заменить $pdo->getChunk() на $modx->getChunk(), то выйдет уже 8 секунд.
То есть, в данном конкретном примере парсинг чанков MODX медленнее pdoTools в 3000 раз. Это говорит о необходимости упрощать чанки, минимизировать условия и использовать pdoTools.
Быстрые плейсхолдеры
Самые простые условия «пусто/не пусто» заменяются «быстрыми плейсхолдерами». Работает это так:
- В чанке должен быть тег, например
[[+tag]] - В чанке должен быть специальный HTML комментарий:
<!--pdotools_tag значение, если тег не пуст--> <!--pdotools_!tag значение, если тег пуст-->
Комментарий именуется исходя из префикса pdotools_ и имени тега. Префикс меняется параметром &nestedChunkPrefix.
Почему именно комментарии? На случай обработки чанка не pdoTools — тогда комментарий просто не отобразится.
Пример использования:
$tpl = '@INLINE
<p>[[+tag]]</p>
<!--pdotools_tag [[+tag]] - значение, если тег не пуст-->
<!--pdotools_!tag значение, если тег пуст-->';
$pls = array('tag' => 1);
echo $pdo->getChunk($tpl, $pls);
$pls = array('tag' => 0);
echo $pdo->getChunk($tpl, $pls);
Результат:
1 - значение, если тег не пуст
значение, если тег пуст
Внутрь быстрого плейсхолдера можно вставлять другие плейсхолдеры и его оригинальное значение. Функционал небольшой по сравнению с фильтрами MODX, но зато очень быстрый.
Быстрый режим обработки
Параметр &fastMode выключает передачу плейсхолдеров в родной парсер MODX. Всё что не смог обработать pdoParser будет просто вырезано.
В последних версиях pdoTools его использовать нет нужды, потому что если pdoParser всё обработал и в чанке не осталось ни одного [[+tag]], результат отдается сразу без запуска modParser.
pdoFetch — класс для работы с базой данных
Этот класс предназначен для работы с любыми таблицами базы данных, неважно какими — лишь бы у MODX был к ним доступ и модель. pdoFetch создает запрос через xPDO, а выполняет через PDO, что дает защиту, гибкость и скорость.
Инициализация pdoFetch
Объект запроса xPDOQuery создается методом makeQuery() исходя из переданных параметров. По умолчанию работает с modResource, но можно указать другой класс.
Важно учитывать, что метод modX::getService() всегда возвращает уже загруженный класс, если он есть. То есть, если вы (или какой-то сниппет) уже проинициализировали pdoFetch, то получите именно этот экземпляр с уже установленными параметрами запроса.
Чтобы гарантированно применить свои параметры используйте pdoFetch::setConfig():
$pdo = $modx->getService('pdoFetch');
$pdo->setConfig(array('class' => 'modUser'));
Метод setConfig может сразу загружать указанные модели компонентов:
$pdo->setConfig(array(
'class' => 'msResourceFile',
'loadModels' => 'ms2gallery'
));
pdoTools не знает какой класс принадлежит какому компоненту, поэтому нужно указать директорию дополнения в /core/components.
Создание запроса — метод makeQuery
Создает объект xPDOQuery и добавляет его в приватное свойство класса pdoFetch. Запрос создается для указанного класса или для modResource по умолчанию.
Основная цель pdoFetch — выбрать все данные за один запрос. Если выбираются TV-параметры к ресурсу, то запросов приходится делать несколько.
Работа с TV-параметрами
Метод addTVFilters
Преобразовывает параметр &tvFilters от getResources в понятные для pdoFetch параметры: where и includeTVs. Сам ничего особо не делает, только разбирает чужой формат запроса и передает дальше.
Если вы умеете пользоваться параметром where, то tvFilters вам не нужен.
Метод addTVs
Очень полезный метод — подключает TV-параметры, указанные списком в &includeTVs. Чем больше TV вы укажете, тем больше нужно будет сделать JOIN таблицы modTemplatevarContent. В принципе, это не особо влияет на скорость.
JOIN операции — метод addJoins
Этот метод получает параметры из конфига и отвечает за все подключения таблиц. Например, addTVs сам ничего не подключит, он только разбирает includeTVs и складывает параметры в leftJoin.
Типы присоединения таблиц
leftJoin — выбираются все записи первой (левой) таблицы, даже если они не соответствуют записям во второй (правой) таблице. Используется для присоединения к ресурсу TV-параметров, так как мы не знаем есть они или нет, а вот ресурс нужно выбрать всегда.
rightJoin — выбираются все записи второй (правой) таблицы, даже если они не соответствуют записям в первой (левой) таблице.
innerJoin — внутреннее объединение двух таблиц. Если для строки из одной таблицы нет соответствия в другой, такая строка исключается. innerJoin всегда возвращает данные сразу из двух таблиц.
Пример присоединения таблиц в PHP
Указание параметров для присоединения в pdoFetch:
$pdo->setConfig(array(
'class' => 'modUser',
'leftJoin' => array(
'Profile' => array(
'class' => 'modUserProfile',
'on' => 'modUser.id = Profile.internalKey',
)
),
'select' => array(
'modUser' => '*',
'Profile' => 'fullname,email',
)
));
Мы выбираем класс modUser, затем присоединяем к нему класс modUserProfile под псевдонимом Profile. Присоединение производим по колонке id у modUser и internalKey у modUserProfile. Затем указываем какие столбцы нужны: для modUser все, а для Profile только полное имя и email.
Пример в сниппете через JSON
При вызове сниппетов нельзя указывать массивы, поэтому параметры нужно превратить в JSON:
[[!pdoResources?
&class=`modUser`
&leftJoin=`{
"Profile": {
"class": "modUserProfile",
"on": "modUser.id = Profile.internalKey"
}
}`
&select=`{
"modUser": "*",
"Profile": "fullname,email"
}`
&showLog=`1`
&sortby=`modUser.id`
&sortdir=`ASC`
]]
Лог pdoTools покажет:
0.0000799: pdoTools loaded
0.0000319: xPDO query object created
0.0005212: leftJoined modUserProfile as Profile
0.0001311: Added selection of modUser: ...
0.0000789: Added selection of modUserProfile: fullname, email
0.0000360: Sorted by modUser.id, ASC
0.0019310: SQL executed
0.0001349: Total rows: 3
Группировка — метод addGrouping
Этот метод добавляет группировку в запрос. Нужен только если вы используете JOIN, и одной строке левой таблицы соответствует несколько строк правой.
Обычно группировка нужна для подсчета количества правых строк. Например, количество файлов для каждого ресурса:
[[!pdoResources?
&parents=`0`
&class=`modResource`
&loadModels=`ms2gallery`
&leftJoin=`{
"Image": {
"class": "msResourceFile",
"on": "modResource.id = Image.resource_id AND Image.parent = 0"
}
}`
&select=`{
"modResource": "*",
"Image": "COUNT(Image.id) as images"
}`
&groupby=`modResource.id`
&showLog=`1`
&sortby=`id`
]]
Без группировки по modResource.id получим ровно один результат, потому что MySQL решит, что мы считаем общее количество для всех строк. С группировкой счетчик работает для каждой строки modResource отдельно.
Выбор полей — метод addSelects
Правила выборки полей:
- Если вы не делаете JOIN, то select можно указывать строкой:
&select=`id,pagetitle,longtitle` - При использовании JOIN нужен массив JSON:
&select=`{ "modResource": "id,pagetitle,longtitle", "Image": "url" }` - Если используются псевдонимы в select, обязательно нужно указать псевдоним таблицы:
&select=`{ "modResource": "id,pagetitle", "Image": "Image.url as image" }` - Перечисление всех полей можно заменять звездочкой:
&select=`{ "modResource": "*", "Image": "Image.url as image" }`
Все ошибки JOIN, Select и Group смотрите в логе pdoTools.
Условия выборки — метод addWhere
Очень важный метод, который берет параметр &where, разбирает его и добавляет условия в запрос.
Задается массивом:
&where=`{"id:>": "15", "published:!=": "0"}`
Если подключены таблицы, можно фильтровать по ним:
&leftJoin=`{
"Image": {
"class": "msResourceFile",
"on": "modResource.id = Image.resource_id AND Image.parent = 0"
}
}`
&where=`{
"published:!=": "0",
"Image.active": "1"
}`
Если у полей таблицы могут быть одинаковые столбцы (обычно id), нужно указывать имя колонки с таблицей:
&where=`{
"modResource.id:>": "15",
"published:!=": "0",
"Image.active": "1"
}`
Фильтрация по TV-параметрам
При фильтрации по подключенным TV псевдонимы обычно указывать не нужно за счет специального метода replaceTVCondition:
&includeTVs=`image,file,mytv`
&where=`{
"image:LIKE": "%yandex.ru%",
"OR:file:=": "1",
"OR:text:!=": ""
}`
Если автозамена не сработает, фильтруйте вот так:
&includeTVs=`image,file,mytv`
&where=`{
"TVimage.value:LIKE": "%yandex.ru%",
"OR:TVfile.value:=": "1",
"OR:TVtext.value:!=": ""
}`
TV присоединяются как TVимятв и фильтровать нужно по значению value.
Чистый SQL в условиях
Если не получается указать нужное условие массивом для xPDO, используйте массив с одной строкой чистого SQL:
&where=`["
TVimage LIKE '%yandex%' OR (TVfile.value = 1 AND TVtext.value != '')
"]`
Обратите внимание на квадратные скобки вместо фигурных. Такое SQL условие попадет в запрос без дополнительных обработок, поэтому смотрите лог на предмет ошибок.
Сортировка — метод addSort
Этот метод добавляет в запрос сортировку и умеет принимать как строку, так и массив. Для простой сортировки по одному полю нужно указать два параметра:
&sortby=`publishedon`
&sortdir=`ASC`
Если в запросе есть JOIN, лучше указывать с именем таблицы:
&sortby=`modResource.publishedon`
&sortdir=`ASC`
Для сортировки по нескольким полям указывайте массив поле => направление:
&sortby=`{
"modResource.publishedon": "ASC",
"modUser.id": "DESC"
}`
Выполнение запроса и возврат результатов
Запрос подготавливается методом prepareQuery и выполняется через PDO.
Параметр &return определяет что вернет метод run():
- sql — строка с готовым SQL запросом, сам он не выполняется
- ids — список с ID подходящих объектов через запятую (для передачи другому сниппету)
- data — массив с результатами (при вызове через сниппет вы получите слово Array)
- tpl — результат запроса, оформленный в указанный чанк
&tpl
У сниппетов по умолчанию &return=tpl, а если есть параметр &returnIds, то ids.
Обработка результатов
После выполнения запроса метод run() вызывает prepareRows() — его цель прогнать результаты и подготовить для вывода.
Именно этот метод отвечает за раскодировку JSON полей и подготовку TV, если указаны &prepareTVs или &processTVs.
Также вызывается checkPermissions() — он проверяет разрешения, указанные в одноименном параметре. Учтите, что для проверки разрешений приходится создавать объекты xPDO, что замедляет работу:
&checkPermissions=`list,view`
Методы getArray и getCollection
Эти два метода нужны для быстрой замены родным методам MODX: getObject и getCollection. В отличие от них, они возвращают массивы, а не объекты.
Пример использования getArray:
$pdo = $modx->getService('pdoFetch');
$res = $pdo->getArray('modResource', 1);
print_r($res);
Пример использования getCollection:
$pdo = $modx->getService('pdoFetch');
$resources = $pdo->getCollection('modResource');
foreach ($resources as $res) {
print_r($res);
}
Эти методы всегда выполняются отдельным экземпляром, чтобы не мешать работающему сниппету. Они выполняются изолированно. Получить вывод лога от них можно только через специальный плейсхолдер:
$pdo = $modx->getService('pdoFetch');
$res = $pdo->getArray('modResource', 1);
print_r($modx->getPlaceholder('pdoTools.log'));
Первым параметром указывается класс для работы, вторым условие where, а третьим любой набор параметров. Например, вот так будет выглядеть выборка всех файлов Тикета:
$files = $pdo->getCollection('TicketFile', array('parent' => 1));
print_r($files);
Пример с JOIN операцией:
$files = $pdo->getCollection('TicketFile', array(), array(
'innerJoin' => array(
'Ticket' => array(
'class' => 'Ticket',
'on' => 'Ticket.id = TicketFile.parent'
)
),
'select' => array(
'TicketFile' => '*',
'Ticket' => 'pagetitle'
),
'sortby' => array(
'TicketFile.id' => 'ASC'
)
));
print_r($modx->getPlaceholder('pdoTools.log'));
print_r($files);
Как видите, эти методы очень удобны для использования в своих сниппетах. На них можно переложить основную работу по добыче данных из БД.
pdoParser — быстрый парсер тегов MODX
pdoParser является заменой класса modParser. Его задача — быстро разбирать теги MODX без создания объектов, как это делает оригинальный парсер.
Обработка простых плейсхолдеров
pdoParser умеет работать только с простыми тегами без фильтров и условий:
[[%tag]]— строка лексикона[[~id]]— ссылка[[+tag]]— обычные плейсхолдеры[[++tag]]— системные плейсхолдеры[[*tag]]— плейсхолдеры ресурса[[#tag]]— плейсхолдеры FastField
Теги FastField
Специальные теги FastField были предложены Виталием Киреевым в одноименном дополнении. После согласования с автором, pdoParser был обучен работе с ними.
FastField умеет:
- Выводить поля ресурсов:
[[#15.pagetitle]],[[#20.content]] - Выводить TV-параметры ресурсов:
[[#15.date]],[[#20.some_tv]] - Выводить массивы ресурсов:
[[#12.properties.somefield]],[[#15.size.1]] - Выводить глобальные массивы:
[[#POST.key]],[[#SESSION.another_key]] - Распечатывать массивы для отладки:
[[#15.colors]],[[#GET]],[[#12.properties]]
Цифра после решетки — это ID ресурса, от которого нужно выбрать данные.
Все эти теги pdoTools обрабатывает без создания объектов modElement, поэтому работает быстрее чем родные методы MODX. Если плейсхолдер вызван с параметрами, он уходит в родной modParser.
Шаблонизатор Fenom
С версии 2.0 в состав pdoTools входит шаблонизатор Fenom. Работает только при включенном pdoParser и если разрешен в системных параметрах.
Возможности Fenom
- Компилируется в нативный PHP код, который выполняется гораздо быстрее тегов MODX — прирост в среднем 30% — 50%
- Может работать и в чанках и на страницах сайта
- Теги Fenom и MODX не мешают друг другу и работают одновременно
- Если в чанке нет плейсхолдеров MODX, парсер MODX не запускается
- Если в чанке нет тегов Fenom, он тоже не запускается
- Поддерживаются даже @INLINE чанки
- Не нужно никак менять или переписывать свои сниппеты — всё работает через методы
pdoTools::getChunk()иpdoTools::parseChunk()автоматически - Все ошибки компиляции пишутся в системный журнал
Системные настройки Fenom
- pdotools_fenom_default — включает обработку синтаксиса Fenom во всех чанках сайта
- pdotools_fenom_parser — включает обработку синтаксиса Fenom на страницах сайта (контент ресурсов, шаблоны). По умолчанию отключено.
- pdotools_fenom_php — включает возможность выполнения произвольных функций PHP в шаблонах через
{$.php.функция()}. Опция очень опасная, поэтому отключена по умолчанию. - pdotools_fenom_modx — работа с объектами modX и pdoTools через переменные
{$modx}и{$pdoTools}. Если вы не доверяете своим менеджерам, выключите её, потому что через объект modX можно удалить начисто весь сайт. - pdotools_fenom_cache — включает кеширование чанков через кешер MODX. Стоит использовать только на продакшн сайтах при больших и сложных чанках.
Порядок запуска шаблонизатора
Если включен pdoParser и системная опция pdotools_fenom_parser, шаблонизатор запускается до парсера MODX. В этот момент все кешированные чанки и сниппеты на странице обработаны и вы можете использовать конструкции:
{if $.get.test == 1}
[[!pdoResources?parents=`0`]]
{else}
[[!pdoMenu?parents=`0`]]
{/if}
В зависимости от $_GET['test'] на странице будет запущен или один сниппет или другой. Парсер MODX же запустил бы оба и результат выполнения одного неподходящего просто не показал.
Внутри чанков Fenom всегда выполняется в первую очередь, позволяя разделять их содержимое для MODX в зависимости от условий.
Вызов тегов Fenom на страницах сайта никак не кешируется.
Кеширование чанков Fenom
По умолчанию этот функционал отключен. Но вы можете включить системную настройку pdotools_fenom_cache и тогда скомпилированные шаблоны будут сохранены в /cache/default/fenom/.
Чанки из БД кэшируются под своими ID, а INLINE именуются как хеш от своего содержимого:
- Обычный чанк:
cache/default/fenom/chunk/90.cache.php - INLINE чанк:
cache/default/fenom/inline/35e115c27fdc3814b6f41a1015aa67e6.cache.php
Отсюда следует, что нормальные чанки из БД кэшируются намертво и обновляются только при очистке системного кэша, а INLINE чанки при изменении контента сохраняются под новым именем и весь кэш чистить не нужно.
При первом запуске с пустым кешем pdoTools получает нужный чанк, определяет его тип и отдает в Fenom. Тот компилирует шаблон и сохраняет его во внутренний кэш pdoTools методом setStore(). Этот кэш находится в ОЗУ и сохраняется только на время выполнения скрипта.
Если включена опция pdotools_fenom_cache, исходный код скомпилированного шаблона сохраняется на HDD сервера, и при следующем запуске Fenom уже не нужно его компилировать.
Вопрос в том, что для вас будет быстрее — поднять скомпилированный шаблон из кэша или скомпилировать его заново. Обычно на маленьких и простых чанках выигрыша нет, а на больших и сложных разница уже может быть. Время компиляции и работы с кэшем выводится в &showLog=1.
Пример использования Fenom
Стандартный чанк из компонента Tickets:
<div class="comments">
[[+modx.user.id:isloggedin:is=`1`:then=`
<span class="comments-subscribe pull-right">
<label for="comments-subscribe" class="checkbox">
<input type="checkbox" id="comments-subscribe" value="1" [[+subscribed:notempty=`checked`]] />
[[%ticket_comment_notify]]
</label>
</span>
`:else=``]]
<h4 class="title">[[%comments]] (<span id="comment-total">[[+total]]</span>)</h4>
<div id="comments-wrapper">
<ol class="comment-list" id="comments">[[+comments]]</ol>
</div>
</div>
Тот же чанк, переписанный для работы с Fenom:
<div class="comments">
{if $modx->user->isAuthenticated($modx->context->key)}
<span class="comments-subscribe pull-right">
<label for="comments-subscribe" class="checkbox">
<input type="checkbox" id="comments-subscribe" value="1" {$subscribed != '' ? 'checked' : ''} />
{$modx->lexicon('ticket_comment_notify')}
</label>
</span>
{/if}
<h4 class="title">{$modx->lexicon('comments')} (<span id="comment-total">{$total}</span>)</h4>
<div id="comments-wrapper">
<ol class="comment-list" id="comments">{$comments}</ol>
</div>
</div>
Как видите, синтаксис Fenom более читаемый и привычный для PHP разработчиков.
Заключение
Три класса pdoTools работают в связке, обеспечивая максимальную производительность:
- pdoTools — основной класс для логирования, кеширования и работы с чанками
- pdoFetch — мощный инструмент для работы с базой данных через PDO с поддержкой JOIN и сложных запросов
- pdoParser — быстрый парсер тегов MODX с поддержкой шаблонизатора Fenom
Используйте эти классы в своих разработках для создания быстрых и эффективных решений на MODX.






