- PVSM.RU - https://www.pvsm.ru -
Хочу представить вашему вниманию свою разработку по быстрому выводу контента на сайтах MODX Revolution.
Как известно, эта система целиком построена на собственной ORM под названием xPDO. Она очень упрощает работу, позволяет писать один универсальный код для разных БД, и еще много чего.
К сожалению, она не может похвастаться скоростью вывода (как, наверное, вообще любая ORM), поэтому я попробовал совместить её плюсы с обычным PDO, добавить лучшую работу с чанками и сделать удобную библиотеку для MODX.
Основные особенности:
Начну с последнего пункта.
Изначально pdoTools был придуман как библиотека для работы других компонентов, например его использует Tickets [1].
Со временем стало очевидно, что он позволяет с минимальными затратами написать неплохой пакет инструментов, способных заменить стандартные сниппеты MODX.
pdoResources
Сниппет для выборки ресурсов, может заменить getResources. Он поддерживает почти все его возможности, и бладает особенностями:
— подключение других таблиц через разные JOIN
— можно указывать, что именно выбирать из колонок таблиц
— гибкие условия выборки, вплоть до указания чистого SQL
При этом сниппет работает раз в 5 — 10 быстрее.
pdoMenu
Сниппет для генерации меню сайта. Может заменить Wayfinder, поддерживает почти все его параметры и чанки.
Работает быстрее, особенно при первом запуске с холодным кэшем.
pdoPage
Замена для getPage. Генерирует гораздо более правильную пагинацию, и не позволяет пихать некорректные запросы в параметры запроса page и limit.
pdoUsers
Сниппет, который выводит пользовтаелей сайта, умеет фильтровать их по группам и ролям.
pdoCrumbs
Быстрая генерация хлебных крошек, заменяет BreadCrumb.
pdoNeighbors
Вывод соседних документов страниц. То есть: следующий, предыдущий и родитель. Очень удобно использовать для навигации по новостям.
pdoField
Сниппет, получающий любое поле ресурса или его родителя, включая ТВ параметр. Заменяет getResourcesField и UltimateParent.
Умеет выводить «значение по умолчанию».
pdoSitemap
Генерация карты сайта. Очень быстрая замена GoogleSiteMap, разница до 12 раз.
На самом деле, при замене стандартных сниппетов аналогами из pdoTools, средний сайт начинает бегать быстрее раза в 2-3. Вы можете заглянуть на страницу документации и подробнее ознакомиться с параметрами и примерами сниппетов здесь [2].
Прелесть моего дополнения в том, что оно не требует никаких особых манипуляций. Вы просто устанавливаете его из репозитория и можно пользоваться. Если что-то не устраивает, глючит, работает не так, как вы ожидали — старые родные сниппеты по-прежнему с вами, можно использовать их.
А теперь я расскажу, за счет чего pdoTools быстро работает.
Для каждой таблицы в MODX существует описание в .map файле. Из коробки система поддерживает 2 базы данных: MySQL и MSSQL, поэтому все запросы в pdoTools генерируются через xPDO.
Начало всегда одинаково:
$q = $modx->newQuery('modResource');
$q->select(array('id', 'pagetitle', 'content'));
$q->sortby('id', 'asc');
$q->limit(10);
А вот дальше мы можем выбрать или объекты:
$resources = $modx->getCollection('modResource', $q);
foreach ($resources as $resource) {
print_r($resource->toArray());
}
Или массивы:
if ($q->prepare() && $q->stmt->execute()) {
$resources = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($resources as $resource) {
print_r($resource);
}
}
Классический путь MODX Revolution, который используется в компонентах его авторов — выборка через xPDO и дальнейшая работа с объектами. Это удобно, конечно — ведь в модели можно прописать разные преобразования для полей объектов, и проверки.
Но это и очень медленно, к сожалению. Поэтому я использую второй путь — выборку через PDO. Это быстрее в несколько раз.
Чанки, если кто не знает — это такие элементы в дереве MODX, которые содержат только HTML. Они нужны для оформления работы PHP скриптов и отделяют логику от представления в системе.
Вот обычный чанк:
<p>[[+idx]]. <a href="/[[+uri]]">[[+pagetitle]]</a></p>
В чанках могут быть специальные команды для парсера, например:
<p>[[+idx]]. <a href="/[[+uri]]">[[+menutitle:isempty=`[[+pagetitle]]`]]</a></p>
Каждый тег [[+key]] — это будущий объект в парсере MODX. К нему можно указывать разные параметры, фильтры и вообще, программировать таким образом.
Это столько же круто, сколь и медленно.
Поэтому в pdoTools чанки предварительно обрабатываются — всё что можно, заменяется банальным str_replace() из полученнных данных, затем заменяются ссылки [[~[[+id]]]], затем плейсхолдеры лексиконов [[%key]], в вот все, что осталось (10% от изначальной работы) отправляется в парсер MODX.
Конечный результат никак не отличается, но скорость такой обработки в разы выше стандартной.
Пользоваться этим очень просто:
$pdo = $modx->getService('pdoTools');
return $pdo->getChunk('имячанка', array('массив со значениями для подстановки'));
В отиличии от оригинального modX::getChunk(), в pdoTools::getChunk() мы можем пользоваться не только уже подготовленными чанками, но и сразу указывать их с помощью биндинга INLINE [3]:
$pdo = $modx->getService('pdoTools');
$tpl = '@INLINE <p>[[+idx]]. <a href="/[[+uri]]">[[+pagetitle]]</a></p>';
$array = array(
'idx' => 1,
'pagetitle' => 'Имя страницы',
'url' => '/page.html'
);
return $pdo->getChunk($tpl, $array);
pdoTools и его сниппеты стараются уложить всю работу в 1 запрос к базе данных. Поэтому все указанные ТВ параметры присоединяются через LEFT JOIN.
Становится очень удобно фильтровать по ТВ, ведь можно просто указать:
[[!pdoResources?
&parents=`2`
&includeTVs=`myTV`
&where=`{"myTV:>":10}`
]]
И вы получите все ресурсы, из контейнера с id = 2 и значением ТВ myTV больше 10. Можно указывать довольно сложные условия и выборки, поэтому я сделал систему логирования:
Почти все сниппеты понимают параметр &shoLog=`1` и выводят менеджеру такую портянку:
По ней очень удобно строить условия и отлаживать запросы в БД.
Библиотека подключается через modX::getService() вот так:
// Если нам нужны только основные функции
$pdo = $modx->getService('pdoTools');
// Если нам нужна работа с БД
$pdo = $modx->getService('pdoFetch');
Первый позволяет быстро работать с чанками:
$pdo->getChunk();
$pdo->parseChunk();
А второй умеет быстро выбирать ресурсы:
$pdo->getObject('modResource', 1);
$pdo->getCollection('modTemplate', array('id:>=' => 2));
Если их скомбинировать, то вот так будет выглядеть весь ваш сайт:
<?php
// Подключем класс
$pdo = $modx->getService('pdoFetch');
// Указываем шаблон
$tpl = '@INLINE <p><a href="/[[+id]]">[[+pagetitle]]</a></p>';
// Выбираем все ресурсы сайта
$resources = $pdo->getCollection('modResource');
$output = '';
foreach ($resources as $resource) {
// Оформляем
$output .= $pdo->getChunk($tpl, $resource);
}
// И добавляем лог
$output .= '<pre>'.$pdo->getTime().'</pre>';
return $output;
Как вам вывод 2012 страниц сайта за полсекунды?
Это очень краткая информация о возможностях pdoTools.
Компонент разрабатывается уже почти год и обладает широчайшими возможностями. Честно говоря, трудно описать все, что он умеет, но я стараюсь.
Ссылка на документацию [2].
Ссылка на репозиторий [2].
Свежие версии в репозитории Simple Dream [4].
Стабильные версии в официальном репозитории [5].
Потестировать без заморочек можно на modx-test.com [6].
Автор: bezumkin
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/modx/46669
Ссылки в тексте:
[1] Tickets: http://habrahabr.ru/post/159773/
[2] здесь: http://bezumkin.ru/modx/pdotools/
[3] INLINE: http://habrahabr.ru/users/inline/
[4] в репозитории Simple Dream: http://store.simpledream.ru/pdotools
[5] в официальном репозитории: http://modx.com/extras/package/pdotools
[6] modx-test.com: http://modx-test.com
[7] Источник: http://habrahabr.ru/post/199062/
Нажмите здесь для печати.