Парсер
Последнее обновление not available | История страницы | Улучшить эту страницу | Сообщить о проблеме
Support the team building MODX with a monthly donation.
The budget raised through OpenCollective is transparent, including payouts, and any contributor can apply to be paid for their work on MODX.
Backers
Budget
$204 per month—let's make that $500!
Learn moreЗачем нужны чанки? Они отделяют представление от логики. В большинстве случаев это нужно, чтобы пользователи могли менять поведение установленных extras.
В чанках и шаблонах MODX можно использовать разные типы плейсхолдеров:
-
[[+tag]]: обычный плейсхолдер, заменяется значением при обработке чанка -
[[++setting]]: системные настройки изmodX::config -
[[*field]]: поле текущего ресурса в свойствеmodX::resource -
[[%lexicon]]: запись из лексикона для строк из словарей extras -
[[~number]]: ссылки на ресурсы -
[[snippet]]: кэшируемый сниппет -
[[!snippet]]: некэшируемый сниппет -
[[$chunk]]: чанк
Любой тег можно вызвать некэшируемым, если поставить восклицательный знак в начале. Любой тег можно отключить минусом в начале.
-
[[!uncached_snippet]] -
[[-!disabled_snippet]]
Как именно парсер MODX обрабатывает эти теги?
modParser собирает все теги из чанка регулярными выражениями, создаёт из них объекты modTag и вызывает их метод process(). Каждый тег в чанке это один экземпляр modTag для modParser.
Если вы используете output filters для тегов, это ещё один объект xPDO. Если output filter это сниппет MODX, modParser будет обрабатывать его каждый раз, когда встретит в чанке.
Если в чанке 3 сниппета и из БД приходит 10 записей, вы получите 30 вызовов сниппетов.
modParser рекурсивный: если тег нельзя обработать сразу, он останется на следующую итерацию. Сначала обрабатываются все кэшируемые теги, затем дополнительно все некэшируемые.
Если для некэшируемого плейсхолдера на странице нет значения, modParser попробует разобрать его до 10 раз (по умолчанию).
Поэтому сложный чанк может разбираться очень долго.
pdoParser¶
Это третий основной класс pdoTools. Он пытается разобрать все простые теги сам. Простые теги: [[+tag]], [[*field]], [[%lexion]], [[~number]] и [[~[[+id]]]].
Их нужно вызывать без output filters, чтобы pdoTools мог просто заменить их значениями без объектов modTag, через обычный str_replace().
Если после pdoTools остаются теги, он вызовет modParser для их разбора. Об этом можно прочитать в предыдущем разделе.
По умолчанию pdoParser это простой препроцессор перед modParser. Поэтому чанки в pdoTools всегда чуть (или сильно) быстрее.
Fenom¶
pdoTools 2.0 приносит встроенную поддержку шаблонизатора Fenom. Хорошая новость: в репозитории на GitHub есть документация на английском. Почему Fenom? Он лёгкий, простой, быстрый, гибкий и русский.
Fenom работает иначе. Он компилирует чанк в PHP-код и кэширует его в памяти. Затем pdoTools передаёт массив значений в этот PHP-код, и он выполняется.
Рекурсивных итераций нет. Один проход на один чанк за раз. Если значения для плейсхолдера нет, оно просто пустое, и никто не заменит его позже. Логика честнее, на мой взгляд.
Синтаксис Fenom похож на Smarty, подробности в официальной документации. Ниже только использование с MODX:
-
{$placeholder}или{$_pls['placeholder']}: для плейсхолдеров с точками или дефисами (TV). -
{$_modx->resource.field}или{$_modx->resource['field']}: для массива текущего ресурса (не объекта!). -
{$_modx->config.setting}или{$_modx->config['setting']}: для системных настроек из массиваmodX::config. -
{$_modx->user.proprety}: значение из смешанного массива свойств modUser и modUserProfile. -
{$_modx->context.key}: значение из массива текущего modContext. -
{$_modx->lexicon('key')}и{$_modx->lexicon->load('dict')}: строки лексикона и загрузка словарей -
{$_modx->makeUrl(number)}: для формирования url -
{$_modx->runSnippet('snippetName', ['key' => 'value'])}: для сниппетов -
{$_modx->getChunk('chunkName', ['key' => 'value'])}: для чанков
Как видите, доступна безопасная переменная {$_modx}. Это не объект modX, а другой объект из pdoTools только с безопасными функциями.
Менеджер по умолчанию не получит доступ к объекту modX из Fenom-чанков. Исходники {$_modx} здесь.
Вторая служебная переменная {$_pls}. Она нужна для плейсхолдеров с точками или дефисами. Переменные Fenom компилируются в PHP, а в PHP нельзя использовать точки или дефисы в именах. Поэтому можно использовать
{$_pls['my.tv']} for placeholders with dots or dashes
or
{$pagetitle} for placeholders without it
Заполнение плейсхолдеров¶
Fenom работает за один проход. В отличие от парсера MODX, он не рекурсивный.
Весь шаблон за один проход даёт высокую скорость, но учитывайте, что плейсхолдеры будут доступны только после работы соответствующего сниппета
Например: нужно получить значение плейсхолдера {$ mse2_query} (поисковый запрос) в форме, но форма поиска выводится выше результатов.
Для этого сначала выполните сниппет mSearch2 и передайте результаты в плейсхолдер, например searchResults:
{'!pdoPage' | snippet : [
'element' => 'mSearch2',
'toPlaceholder' => 'searchResults'
]}
Затем вызовите сниппет формы поиска, где парсер Fenom подставит значение плейсхолдера {$mse2_query}:
{'!mSearchForm' | snippet}
Потом выведите результаты сниппета mSearch2:
{'searchResults' | placeholders}
Если сниппет не может сохранить результат в плейсхолдер, назначьте его переменной Fenom:
{var $date = 'dateAgo' | snippet : ['input' => '2016-09-10 12:55:35']}
...
Your date: {$date}.
Очень похоже на логику обычного скрипта.
Системные настройки¶
Для Fenom есть важные системные настройки:
-
pdotools_fenom_default: использовать синтаксис Fenom в чанках. По умолчанию включено. -
pdotools_fenom_modx: включает очень опасную переменную{$modx}с полным доступом к объектуmodX. По умолчанию выключено, включать не рекомендуется. -
pdotools_fenom_php- включает чистые PHP-функции в чанках. По умолчанию выключено, включать не рекомендуется. -
pdotools_fenom_modifiers: список сниппетов, доступных как output filters. Можно задать и при вызове сниппета. -
pdotools_fenom_parser: включает обработку тегов Fenom на всём сайте. Новичкам не рекомендуется.
Fenom работает с MODX в двух режимах: только в чанках и на всём сайте. Первый режим включён и рекомендуется по умолчанию.
Можно смешивать синтаксис Fenom с MODX:
{$_modx->isAuthenticated($_modx->content.key)}
Hello, {$_modx->user.fullname}!
{else}
[[Login?params...]]
{/if}
Fenom выполнится на первом проходе в чанках, поэтому можно честно разделить их части. В этом примере сниппет Login вызовется только для неавторизованного пользователя. modParser, как известно, выполнит обе части кода и выберет одну для текущего пользователя.
При смешанном синтаксисе вызываются и Fenom, и парсер MODX, и это не лучший вариант для максимальной производительности. Всегда быстрее использовать только Fenom, но к нему можно плавно мигрировать через смешанный синтаксис.
В режиме чанков у Fenom нет недостатков. Это предпочтительный режим работы.
Когда наиграетесь с чанками, можно включить Fenom на весь сайт. Да, это возможно, но нужно знать несколько важных вещей.
- Это не кэшируется как теги MODX. Каждое условие Fenom обрабатывается при каждой загрузке страницы. Для быстрого сайта это часто нормально.
- Теги MODX на странице всегда обрабатываются на первом проходе. Логику нельзя разделить условиями Fenom вместе с тегами MODX. Fenom запустит pdoParser в конце обработки страницы, когда MODX начнёт разбирать оставшиеся некэшируемые плейсхолдеры.
- Fenom остановит обработку страницы на любом «неправильном» условии
{tag}. Любой JSON или javascript на странице может сломать обработку. В таком случае отделите первый символ от фигурной скобки пробелом.
<script>
var y = {"key": "value"}; // will cause an error
var x = { "key": "value" } // it is ok
</script>
Также можно использовать тег {ignore}:
<script>
{ignore}
var y = {"key": "value"}; // it is ok now
{/ignore}
</script>
Запомните эти 3 пункта при включении системной настройки pdotools_fenom_parser. Каждая ошибка компиляции попадёт в лог ошибок менеджера.
А что со скоростью?¶
Моя любимая часть. Сделаем несколько тестов.
Тест MODX:
[[!pdoResources?
&parents=`0`
&tpl=`@INLINE <p>{{+id}}. {{+longtitle:default=`{{+pagetitle}}`}} {{+createdon:dateago}}</p>`
&limit=`1000`
&sortby=`id`
&sortdir=`asc`
&showLog=`1`
]]
И Fenom. Обратите внимание: для использования в чанке нужно указать сниппет dateAgo как модификатор Fenom:
[[!pdoResources?
&fenomModifiers=`dateAgo`
&parents=`0`
&tpl=`@INLINE <p>{$id}. {$longtitle ?: $pagetitle} {$createdon | dateago}</p>`
&limit=`1000`
&sortby=`id`
&sortdir=`asc`
&showLog=`1`
]]
2.7 секунды против 1. Fenom почти в 3 раза быстрее при тех же условиях. Комментарии, думаю, лишние.
Можно сделать ещё один тест с чанками без output modifiers. Всё то же, но чанки такие:
&tpl=`@INLINE <p>{{+id}}. {{+pagetitle}} {{+createdon}}`
&tpl=`@INLINE <p>{$id}. {$pagetitle} {$createdon}</p>`
Fenom снова быстрее, даже когда pdoTools просто делает str_replace() для плейсхолдеров.
Теги FastField¶
Многие знают компонент fastField, который добавляет обработку дополнительных плейсхолдеров вроде [[#15.pagetitle]].
Эта функциональность уже добавлена в pdoParser с разрешения автора и даже немного расширена.
Все теги fastField начинаются с # и содержат либо id ресурса, либо имя глобального массива.
Обычное поле ресурса:
[[#15.pagetitle]]
[[#20.content]]
TV ресурса:
[[#15.date]]
[[#20.some_tv]]
Поля товаров miniShop2:
[[#21.price]]
[[#22.article]]
Массивы ресурсов и товаров:
[[#12.properties.somefield]]
[[#15.size.1]]
Суперглобальные массивы:
[[#POST.key]]
[[#SESSION.another_key]]
[[#GET.key3]]
[[#REQUEST.key]]
[[#SERVER.key]]
[[#FILES.key]]
[[#COOKIE.some_key]]
Можно указывать любые поля в массивах:
[[#15.properties.key1.key2]]
Если не знаете, какие значения в массиве, укажите его целиком, и он выведется полностью:
[[#GET]]
[[#15.colors]]
[[#12.properties]]
Теги fastField можно комбинировать с тегами MODX:
[[#[[++site_start]].pagetitle]]
<pre>
[[#[[++site_start]]]]
</pre>
Сегодня теги FastField не обязательны, потому что Fenom полностью их заменяет:
{var $resource = $_modx->getResource(15)}
{if $resource?}
{$resource.pagetitle}
{/if}
Можно даже получить и вывести несколько ресурсов:
{var $resources = $_modx->getResources(
['published' => 1, 'deleted' => 0],
['sortby' => 'id', 'sortdir' => 'ASC', 'limit' => 50]
)}
{foreach $resources as $resource}
{$_modx->getChunk('@INLINE <p>{$id} {$pagetitle}</p>', $resource)}
{/foreach}
И, конечно, есть глобальные переменные:
{$.session['your_key']}
{$.get['query']} or {$.get.query}
{$.server['REQUEST_URI']}
Support the team building MODX with a monthly donation.
The budget raised through OpenCollective is transparent, including payouts, and any contributor can apply to be paid for their work on MODX.
Backers
Budget
$204 per month—let's make that $500!
Learn more














