[pdoTools] Версия 1.8.8 Улучшенное кэширование

Новая версия с исправлениями и парой приятных улучшения.

Кэширование

В принципе, код компонента уже довольно хорошо оптимизирован, и явных способов еще ускорить его, без потери функциональности, не видно — поэтому я взялся за кэш.

Сейчас его можно использовать в 2х сниппетах: pdoMenu и pdoPage:
[[!pdoPage?
	&parents=`2`
	&cache=`1`
	&cacheTime=`3600`
]]

Важное отличие от getPage состоит в том, что кэширование всегда производится с учетом id посетителя. К примеру, у меня в списке заметок выводится количество непрочитанных комментариев. Раньше такое кэшировать было нельзя, ибо тогда все видели одни и те же цифры, а теперь — можно.

Гости видят одни результаты, авторизованные пользователи — другие. Лично я закэшировал у себя всё списки тикетов на 120 секунд.

На уровне api в классе pdoTools появились методы getCache и setCache. Можно использовать их напрямую:
$pdo = $modx->getService('pdoTools');
$pdo->setConfig(array('cache' => 1, 'cacheTime' => 3600));

if (!$data = $pdo->getCache('ключ')) {
	$data = array('key' => 'value');
	$pdo->setCache($data, 'ключ');
}

echo '<pre>';
print_r($data);
print_r($pdo->getTime());
В сниппетах pdoMenu и pdoPage примерно такой же код.

Исправления

Убрал заранее прописанные параметры «sortby» и «sortdir» в классе pdoFetch. Они ни на что не влияли, зато могли мешать при вызовах pdoFetch::getCollection().

Добавил новый параметр decodeJSON, установленный по умолчанию в true. Этим параметром вы можете отключить автоматическое декодирование JSON в строках результата, чтобы получить именно то, что хранится в БД.

Исправлена работа с idx в методе pdoTools::defineChunk(). Теперь, если вы указываете
[[!pdoPage?
	&element=`pdoResources`
	&parents=`2`
	&tpl_2=`myTpl`
]]
то чанк для второй строки будет применяться на всех страницах вывода, а не только на первой. Подробности тут.

У сниппета pdoMenu исправлен параметр tplParentRowActive — раньше он просто не работал.

Заключение

Новая версия уже пару дней лежит в репозиториях, возможно вы уже на неё обновились.

Надеюсь, вам понравится новое кэширование — я им пользуюсь уже какое-то время, нареканий нет.

Следующая заметка
[MinifyX] Новая бета версия со встроенным Munee
Предыдущая заметка
[miniShop2] Версия 2.1.2 Поддержка файлов в галерее


Комментарии ()

  1. Павел Левин 11 ноября 2013, 12:02 # 0
    Возник небольшой вопрос, недавно заметил… (вчера), что при вызове pdoResources первым делом кэшируется шаблон указанный в параметрах, сооствественно все условия, которые прописаны в шаблоне далее не выполняются к примеру:

    [[+isfolder:is=`1`:then=`
    Лично я использую это условие в шаблоне для вывода родителя в определенной обертке.

    К сожалению, когда я указываю, что вызов можно кэшировать, а это толпа документов т.к. «словарь терминов», то условие не работает как требуется, на выходе я получаю текст «буква» (родитель), далее отформитированные термины и опять «буква» и т.д.

    Я не понял в чем зависимость от кэширования и условия в шаблоне/чанке. Возможно я не верно подошел к задаче, но отталкивался от имеющего багажа знаний и доступного функционала.
    1. Василий Наумкин 11 ноября 2013, 15:10 # 0
      Для подобных вещей есть conditionalTpls и даже prepareSnippet.

      Не нужно программировать на фильтрах.
      1. Павел Левин 11 ноября 2013, 19:54 # 0
        Спасибо, как будет время прочитаю, вникнусь, попробую.

        но... для чего их придумали тогда?
        1. Василий Наумкин 11 ноября 2013, 19:56 # 0
          Вдумайся в словосочетания «фильтр вывода» и «программирование».

          Очевидно, что фильтры нужны в очень простых случаях: заменить пустую строку на «нет результатов» или подставить символ валюты, если плейсхолдер больше 0.

          Для всего остального нужно использовать php. Многие этого не понимают, и потом плачутся в интернете, что «Рево глючит и тормозит».
          1. Павел Левин 11 ноября 2013, 20:01 # 0
            Понятно, разберемся значит)

            — Нет нерешаемых задач.
    2. Павел Левин 13 ноября 2013, 21:18 # 0
      Заметил одну закономерность, если на странице вызывается pdoPage, то следом идущие сниппеты могут и не работать… в частном случае у меня не работает вывод истории просмотров, а на страницах, где идёт вызов пдоРесурс, история выводится.

      так же, если я укзазываю не кешировать pdoPage
      [[!pdoPage?
      то отрубается пол страницы т.е. с момента вызова пдоПейдж

      вызываю так:
      [[pdoPage?
                &elementClass=`modSnippet`
                &element=`pdoResources`
                &showHidden=`[[*first_level]]`
                &tpl=`tpl.pdoResources`
                &tpl_n3=`tpl.pdoResources.clearer`
                &limit=`12`
                &depth=`10`
                &parents=`[[*id]]`
                &hideContainers=`1`
                &pageLimit=`7`
                &pageNavVar=`page.nav`
                &scheme=`full`
              ]]
      м… &scheme=`full` ведь нормально работает?
      1. Василий Наумкин 14 ноября 2013, 05:33 # 0
        Его нельзя вызывать кэшированным, ибо тогда он не сможет смотреть в $_GET и обрабатывать номер страницы, при пагинации.

        Ну а про все остальное — не знаю. Ты очень любишь вложенные чанки и фильтры — может в этом проблема. Используй getPage, если с ним нет проблем.

        &scheme=`full` ведь нормально работает
        Этот параметр d pdoPage остался по ошибке. Если его принимает сниппет, который выбирает и оформляет результаты — тогда будет работать, если нет — нет.
        1. Павел Левин 14 ноября 2013, 13:00 # 0
          Для чистоты эксперимента вставлял вызов в сам шаблон, а не в чанк. Он хорошо работал до обновления. -__-
          1. Павел Левин 14 ноября 2013, 13:05 # 0
            проблему определил, когда указываешь параметр связанный с tpl, любой. Идёт ошибка… не знаю че именно, возможно обрывается код, но лог чист.

            к примеру:
            &tplPage=`@INLINE <li><a href="[[+href]]">[[+pageNo]]</a></li>`

            100% ошибка в этом, но я не знаю что именно там перестаёт работать.
            1. Павел Левин 14 ноября 2013, 16:09 # 0
              Ладно… я смог воспроизвести ошибку на modx-test.com, теперь всё ясно =)

              Вдумайся в словосочетания «фильтр вывода» и «программирование».
              Причина ошибки: Прямой вызов pdoPage в «фильтр вывода»
              1. Василий Наумкин 14 ноября 2013, 16:19 # 0
                У фильтров есть одна большая особенность, наверное ты про нее не знаешь: сначала работает всё, что внутри фильтра.

                Если ты указываешь
                [[+var:default=`[[!pdoPage?]]`]]
                То сначала будет запущен pdoPage, и только потом результаты работы или будут показаны на странице, в зависимости от условия фильтра, или нет.

                Именно поэтому не нужно программировать на фильтрах — это глючит и тормозит. Информация по теме.
                1. Павел Левин 14 ноября 2013, 17:30 # 0
                  М… я особо не понял, но идея с
                  [[[[*longtitle:is=``:then=`*pagetitle`:else=`*longtitle`]]]]
                  вполне себе интересная, жаль не работает
                  1. Сергей 14 ноября 2013, 18:10 # 0
                    Какой-то у вас странный код, разве не так:
                    [[*longtitle:is=``:then=`[[*pagetitle]]`:else=`[[*longtitle]]`]]
                    ?
                    1. Павел Левин 14 ноября 2013, 19:43 # 0
                      в этом весь смысл, чтоб modx в начале вычислил значения параметров (строку), а уже потом работал с данными вызова сниппета и т.п.
                      1. Сергей 14 ноября 2013, 23:59 # 0
                        Да, извините, не сразу понял вашу идею.
          2. Сергей Шлоков 20 ноября 2013, 12:22 # 0
            Василий, вопрос-предложение по механизму джойнов. Может в качестве ключа 1 уровня использовать не класс, а алиас?
            Сайчас логика pdofetch::addJoin() такая:
            {"CLASS":{"class":"CLASS","alias":"ALIAS","on":"ALIAS.field = ALIAS1.field"}
            Но тогда заджойнить 2 одинаковых таблички не получится (например, по createdby и editedby). Ключи первого уровня CLASS должны быть разными. Но тогда они уже не являются классом.
            Может так?
            {"ALIAS":{"class":"CLASS","alias":"ALIAS","on":"ALIAS.field = ALIAS1.field"}
            а соответственно и так:
            {"ALIAS":{"class":"CLASS","on":"ALIAS.field = ALIAS1.field"}
            1. Василий Наумкин 20 ноября 2013, 12:39 # 0
              Не совсем так.

              Сейчас ключ массива используется только если не указан class внутри массива. Так что, можно писать:
              [
              	{"class":"CLASS","alias":"ALIAS1","on":"MAINCLASS.field = ALIAS1.field"},
              	{"class":"CLASS","alias":"ALIAS2","on":"MAINCLASS.field = ALIAS2.field"},
              ]
              

              Но идея все равно хорошая, попробую поменять.
              1. Василий Наумкин 20 ноября 2013, 12:50 # 0
                Попробуй вот этот коммит, должно работать.
                1. Сергей Шлоков 20 ноября 2013, 14:14 # 0
                  Забрал. Спасибо. МегаСуперКласс!
                  А если не полениться и указать связи в схеме, то пишется все в 2 слова :)
                  {"ALIAS":{"class":"CLASS"}}
              2. Dmitry Rodionov 22 апреля 2014, 19:29 # 0
                Важное отличие от getPage состоит в том, что кэширование всегда производится с учетом id посетителя. К примеру, у меня в списке заметок выводится количество непрочитанных комментариев. Раньше такое кэшировать было нельзя, ибо тогда все видели одни и те же цифры, а теперь — можно.
                Логичнее сделать это опционально.
                Это необходимо если страница в интернет магазине тяжелая и надо показывать всем уже кешированный результат а не каждому кешировать отдельно
                1. Василий Наумкин 22 апреля 2014, 21:44 # +1
                  Метод getCacheKey позволяет указать свой id юзера для кэша.
                  [[!pdoPage?
                  	&cache_user=`0`
                  ]]
                  1. Dmitry Rodionov 22 апреля 2014, 22:41 # 0
                    Спасибо, теперь просто идеально, интернет магазин с >9k товаров за 0,15с ;)
                    Наверное правильнее будет если этот параметр указать на сайте docs.modx.pro + так же там бы хотелось видеть описание параметров для сниппетов ms2.
                    1. Василий Наумкин 23 апреля 2014, 06:47 # 0
                      Укажи. И сниппеты опиши.

                      Не зря же у нас открытый репозиторий документации — github.com/bezumkin/Docs
                2. Сергей Шлоков 09 октября 2014, 20:36 # 0
                  Василий, в pdotools::checkPermissions ты берешь $row['id'] у объекта.
                  $object = $this->modx->newObject($this->config['class']);
                  $object->_fields['id'] = $row['id'];
                  
                  А если такого поля нет у класса, то получается пустота. Я понимаю, что он нужен только для лога. Может лучше $modx->getPK('class') прикрутить?
                  1. Василий Наумкин 09 октября 2014, 21:04 # 0
                    Насколько я помню, checkPermissions работает исключительно с наследниками modAccessibleObject, у которых id, как правило, есть.
                    1. Сергей Шлоков 09 октября 2014, 23:16 # 0
                      id есть у modAccessibleSimpleObject, который наследуется от modAccessibleObject, по аналогии с xPDOObject и xPDOOSimpleObject.
                      Вот для информации.
                      1. Василий Наумкин 09 октября 2014, 23:35 # 0
                        И что я не так сказал? Я же не написал «всегда есть id», я написал «как правило есть».

                        Вы мне лучше покажите хоть один объект, которые наследует modAccessibleObject без modResource. Я вот не представляю, зачем это можно делать для не ресурсов, учитывая систему разрешений MODX.

                        Для своих необычных объектов без id, наследников modAccessibleObject нужно как минимум написать свою же админку для работы с разрешениями. Есть примеры?
                        1. Сергей Шлоков 10 октября 2014, 07:59 # 0
                          Собственно, почему я вообще обратил на это внимание — мои объекты наследуются от modAccessibleObject и у некоторых нет поля id. Я в админке с ними не работаю, вся работа идет в front-e.
                          Да собственно, вопрос не принципиальный. Я могу создать свой класс на основе pdoTools и написать как надо. Просто написал тебе для информации.
                          П.С. И все-таки на bezumkin.ru полезной информации очень много. Это я к возможности сохранять в избранное :) Было бы удобно.
                          1. Сергей Шлоков 10 октября 2014, 11:45 # 0
                            Мда. Ты прав. Вся система оказалась заточена только под modResource. Придется свое чего-то придумывать.
                            1. Василий Наумкин 10 октября 2014, 12:20 # 0
                              Есть modUser->hasPermission() — я использую его.

                              Не так гибко, но мне вполне хватает.

                              P.S. Если на bezumkin.ru обновлять Tickets, то надо много всего переделывать, а мне лень. Используй избранное в браузере.
                              1. Сергей Шлоков 10 октября 2014, 12:59 # 0
                                Понял. Спасибо.
                    Добавление новых комментариев отключено.