[pdoTools] Версия 1.1.0 с улучшенным парсером

Портировал и улучшил наработки по рендеру чанков из Tickets в pdoTools. Если кто не знает, это такой компонент для создания очень быстрых сниппетов. На этом сайте, например, почти всё выводится с его помощью.

Сниппеты pdoTools работают очень круто за счет двух основных преимуществ:
1. Запросы в БД через PDO.
2. Собственный метод обработки чанков.

С первым всё понятно, а вот про второе надо рассказать.

Как работает парсер MODX Revolution

При запуске метода modX::getChunk, движок получает его содержимое и собирает в нём свои теги, регулярным выражением. Далее, он определяет класс каждого тега и создаёт его объект, после чего запускает метод process.

Да, для каждого тега создаётся объект и запускается процессинг.

Это довольно медленно, но позволяет нам творить чудеса с фильтрами, вложенными параметрами и прочим, за что мы так любим MODX. Чем меньше вы используете эти прелести, тем быстрее будет работать вывод чанков.

Как работает парсер pdoTools

В pdoTools есть свой собственный метод pdoTools::getChunk, который работает несколько иначе:
1. При первом запуске получает и кэширует чанк в ОЗУ.
2. Заменяет все возможные плеёсхолдеры быстрой функцией str_replace(). Если плейсхолдер указан с фильтрами или другими параметрами — он пропускается.
3. И вот дальше возможно 2 варианта, зависят от параметра fastMode:
. fastMode = 1. Все необработанные плейсхолдеры вырезаются. Максимальная скорость, магия MODX не работает.
3b. fastMode = 0. Запускается парсер MODX для процессинга оставшихся тегов. Обрабатывается только то, что не вышло подставить данными из БД. А это гораааздо меньший объём работы.

То есть, при любом раскладе pdoTools быстрее обработает чанк. Однако, я добавил еще возможность указывать «вложенные чанки».

Мой велосипед вложенных чанков

Что это такое? Это специальные участки кода, которые мой getChunk видит, и вырезает в специальную заначку для последующего использования вашим сниппетом.

Вот пример такого чанка:
<div class="section">
	...
	<i class="icon black icon-comment"></i> [[+comments]] [[+new_comments]]</a></div>
	...
</div>
<!--ticket_new_comments <span class="green">+[[+new_comments]]</span>-->
Здесь вы видите внизу закомментированный кусок, который начинается с префикса ticket_ (префикс настраивается). При первой загрузке чанка pdoTools выделит этот кусок и сохранит себе в pdoTools::elements[имя чанка]['placeholders']['new_comments'].

Смекаете? Дальше вашему сниппету останется организовать логику и подставить значение в плейсхолдер, который находится в нзакомментированной части (там он без префикса). Внимание, в версии 1.2.0 это уже автоматизировано!

Например, вот так:
	...
	$v['new_comments'] = $modx->getCount('TicketComment', $q);
}

if (!empty($pdoFetch->elements[$tpl]['placeholders']['new_comments']) && !empty($v['new_comments'])) {
	$pl = $pdoFetch->makePlaceholders(array('new_comments' => $v['new_comments']));
	$v['new_comments'] = str_replace($pl['pl'], $pl['vl'], $pdoFetch->elements[$tpl]['placeholders']['new_comments']);
}
else {$v['new_comments']= '';}

Таким образом, мы сделали вывод непрочитанных комментариев без фильтра, на чистом php. Это, опять же, гораздо быстрее.
Кстати, теги лексикона [[%key]] тоже обрабатываются по ускоренной схеме, если указаны без параметров и загружен нужный лексикон. Тогда все [[%key]] заменяются на результат работы $modx->lexicon($key).

Выглядит сложно, но это и не каждому надо. А если немного разобраться в теме, так и ничего сложного.
Преимущества:
— В одном чанке можно хранить кучу блоков, которые будут отображаться в зависимости от условий в php.
— Повышенная скорость из-за отсутствия фильтров.
— Экономия на обработке тегов лексикона, если они указаны без параметров.

Вообще, pdoTools рассчитан на программистов, которым нужен лёгкий и удобный инструмент. Кстати говоря, подобные фокусы я делал еще в Evolution, но оно было не так красиво и универсально, как в pdoTools.

Тесты

Вот черновой чанк от miniShop2, для вывода каталога:
<div class="row ms2_product">
	<div class="span2">[[+thumb:notempty=`<img src="[[+thumb]]" width="120" height="90" />`]]</div>
	<div class="row span10">
		<p><a href="[[~[[+id]]]]">[[+pagetitle]]</a>
			<span class="price">[[+price]] [[%ms2_frontend_currency]]</span>
			[[+old_price:gt=`0`:then=`<span class="old_price">[[+old_price]] [[%ms2_frontend_currency]]</span>`:else=``]]
			[[+tags:notempty=`<span class="tags">[[%ms2_frontend_tags]]: [[+tags]];</span>`]]
			[[+color:notempty=`<span class="color">[[%ms2_frontend_color]]: [[+color]];</span>`]]
			[[+size:notempty=`<span class="size">[[%ms2_frontend_size]]: [[+size]];</span>`]]
		</p>
		<p><small>[[+introtext]]</small></p>
		<a href="#" class="ms2_link" data-action="add" data-params='{"id":[[+id]],"count":1}'><i class="icon-barcode"></i> [[%ms2_frontend_add_to_cart]]</a>
		[[%ms2_frontend_add_to_cart?namespace=`minishop2`]]
	</div>
</div>
<!--minishop2_tags , [[+value]]-->
<!--minishop2_color , [[+value]]-->
<!--minishop2_size , [[+value]]-->

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

Пользуемся встроенным логером pdoTools, (который считает время, на каждую операцию) и наблюдаем разницу при использовании getChunk от MODX и pdoTools.
pdoTools fastMode=0
0.0474360: Returning processed chunks
0.0709820: Total time

MODX
0.1156840: Returning processed chunks
0.1395649: Total time

И это при выводе всего 10 товаров. Разница в 2 раза на одной обработке чанков, с одинаковым результатом.

Если вы сможете обойтись вообще без сложных тегов MODX (например, заменив [[~[[+id]]]] на [[+uri]] и т.п.), то можно включить fastMode:
pdoTools fastMode=1
0.0108371: Returning processed chunks
0.0233843: Total time
К примеру, комментарии в Tickets так и выводятся.

Следующая заметка
miniShop2 вышел


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

  1. Мордынский Николай 18 апреля 2013, 13:14 # 0
    Пакет пропал из репозитория после вчерашних глюков modx.com
    1. Василий Наумкин 18 апреля 2013, 13:41 # 0
      Да, молодцы.

      Жду не дождусь, когда построю свой репозиторий с магазином.
      1. Мордынский Николай 18 апреля 2013, 14:04 # 0
        Кстати jevix тоже не подкачивается в тикетах
        1. Мордынский Николай 18 апреля 2013, 17:09 # 0
          minifyx тоже нет
          Извиняюсь, что пишу про них просто в виду плясок с бубном по поводу плагинов я грохнул тестовый сайт на котором у меня крутилась работа последних полутора месяцев и теперь пытаюсь собрать что то покусочкам, а пакетов нет
          1. Василий Наумкин 18 апреля 2013, 18:06 # 0
            Мне сказали
            Our Mongo Database needs to be re-indexed
            it will be restored once that is done

            Надеюсь, завтра всё будет ок. Если не будет — выложу тут.
            1. Alex Vakhitov 18 апреля 2013, 19:31 # 0
              Круто, не знал что у них на Mongo все крутится. Правда смысла не вижу, но все равно круто (:
              1. Мордынский Николай 18 апреля 2013, 21:36 # 0
                ага а в итоге еще потом скжут аур ворд пресс энджин ис брокен сори )))
                1. Alex Vakhitov 19 апреля 2013, 09:36 # 0
                  Не понял о чем ты. Вполне логично что MODX не используется для хранения расширений. Меня просто порадовал тот факт что создатели идут в ногу со временем, но использование там монго как мне кажется необоснованно, проще было держать бд на постгре, а монго использовать для кеша
    2. Дмитрий Иванов 27 июня 2013, 22:54 # 0
      Чёто не пойму, пытаюсь использовать «вложенные чанки», но, как водится, не едет велосипед:

      В чанке myProduct.content ( не много изменённый msProduct.content ) дописал:

      ...
      [[+test]]
      ...
      <!--minishop2_test , Этот плейсхолдер имеет значение: [[+test]]-->
      Но ничего не выводится. В чём может быть прокол?
      1. Василий Наумкин 28 июня 2013, 06:28 # 0
        А он что, проходит через какой-то pdoTools сниппет?

        На сколько я понимаю — нет.
        1. Дмитрий Иванов 28 июня 2013, 08:02 # 0
          Ну да, в этом примере не проходит.
          Изначально я пробовал делать так:

          ...
            </div>
          </div>
          <span class="flags">[[+old_price]] [[+popular]] [[+new]]</span>  // специальные плейсхолдеры
           [[!msOptions@myOptions?name=`color` &selectId=`selColor`]]
          [[!msOptions@myOptions?name=`size` &selectId=`selSize`]]   
          ...
          <!--minishop2_popular <span class="icon-star" title="[[%ms2_frontend_popular]]"><img src="assets/templates/babymart/images/decor/popular.png" /></span>-->
          <!--minishop2_new <span class="icon-flag" title="[[%ms2_frontend_new]]">[[%ms2_frontend_new]]</span>-->
          <!--minishop2_old_price <span class="old_price" title="Старая цена">[[+old_price]] [[%ms2_frontend_currency]]</span>-->
          И выводились значения из БД: 230 0 1 (цена, популярный товар, новый товар ). То есть извлечение данных с помощью pdoTools уже есть.
          1. Дмитрий Иванов 28 июня 2013, 08:39 # 0
            Чтобы упростить задачу, объясню ход мыслей:
            Я так понял, что подстановка значений в плейсхолдер осуществляется автоматически при парсинге чанка если данные извлекаются с помощью pdoTools и код в сниппете самому писать не надо. (так как в этой статье написано «Внимание, в версии 1.2.0 это уже автоматизировано!»).
            1. Дмитрий Иванов 28 июня 2013, 09:16 # 0
              А, ну всё правильно, чанк myProductContent просто вызывается в другом чанке. Надо написать сниппет и вызвать этот чанк с помощью pdoTools и должно заработать.
              1. Дмитрий Иванов 28 июня 2013, 10:41 # 0
                Сделал сниппет productContent с кодом:

                <?php
                /* @var pdoFetch $pdoFetch */
                $pdoFetch = $modx->getService('pdofetch','pdoFetch', MODX_CORE_PATH.'components/pdotools/model/pdotools/',$scriptProperties);
                $pdoFetch->addTime('pdoTools loaded.');
                
                $output = $pdoFetch->getChunk('myProduct.content');
                
                return $output;
                Получается я в чанке itemContent вызываю этот сниппет, а сниппет вызывает чанк myProduct.content. Сделал я это в расчёте на то, что при вызове чанка с помощью pdoTools он автоматически подставит специальные плейсхолдеры.
                Но этого не произошло, всё выводится как раньше просто значениями из БД. Очевидно, я не догоняю в чём ошибка.
                1. Василий Наумкин 28 июня 2013, 11:34 # 0
                  Дима, ты похоже наугад делаешь.

                  1. Нужно передать массив с данными в getChunk
                  2. Нужно префикс указать, по умолчанию он pdotools_.

                  $pdoFetch->config['nestedChunkPrefix'] = 'minishop2_';
                  1. Дмитрий Иванов 28 июня 2013, 11:41 # 0
                    Ну да, практически наугад. Как то нет у меня чёткой картины как это сделать.
                    Насчёт первого пункта:
                    В обычных условиях если, например, данные выводятся с помощью сниппета msProduct — я могу отследить и редактировать все данные поступающие в чанк просто посмотрев код сниппета. Но здесь вывод через tpl.msProduct.content и я в упор не понимаю откуда этот чанк берёт данные. В нём поидее уже есть все нужные данные:
                    [[+old_price]], [[+new]] и [[+popular]]. Они выводятся на странице.
                    То есть я не понимаю чем этот чанк обрабатывается, просто указываешь чанк в коде и он выводит информацию, а как она там появляется я не вижу потому что нет сниппета типа msProductContent или чего то подобного. Я понимаю, что туплю и скорее всего ответ у меня под носом, но уже проковырялся долго и не нашёл.
                    Сейчас попробую установить префикс

                    upd.: не помогло. Ну ладно, решил всё стандартными фильтрами чанков. В целях экономии времени. Потом вернусь к этому, надо разбираться с pdoTools и вообще поглубже покапаться в справке MODx.
                    1. Василий Наумкин 28 июня 2013, 13:21 # 0
                      Если ты про этот чанк, то плейсхолдеры для него выставляет сам класс msProduct, при загрузке страницы.

                      Тут нет, и не должно быть pdoTools. Чанк просто вызывается на странице товара, отсюда и его название.
                      1. Дмитрий Иванов 28 июня 2013, 14:08 # 0
                        Всё понял, спасибо. Мне бы эту строчку ни в жизнь не отыскать без подсказки.
                        Значит надо извлечь данные самостоятельно с помощью pdoTools, а я всё пытался из готовых данных состряпать пирожок.
            2. Михаил 12 августа 2014, 03:29 # 0
              Добрый день. В журнале ошибка "(ERROR @ /index.php) [pdoTools] Error 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay".
              подскажите где это прописать. Спасибо.
              1. Василий Наумкин 12 августа 2014, 06:13 # 0
                В настройках MySQL.
                1. Михаил 12 августа 2014, 07:37 # 0
                  А не могли бы конкретней подсказать где файл подключения к MySQL лежит, куда нужно прописать SET SESSION SQL_BIG_SELECTS=1? доступа к редактированию файла .ini на хосте нет…
                  Если что-то не так написал, подскажите, пожалуйста, что и куда прописать…
                  1. Василий Наумкин 12 августа 2014, 08:01 # 0
                    Читай подробно, отчего возникакет такая ошибка, и думай как исправить.

                    Возможно, это ограничения на хостинге, лично я ни разу такую ошибку в MySql не ловил за всю свою практику.
              Добавление новых комментариев отключено.