[Twiggy] - шаблонизатор TWIG в MODX Revolution

Пакет Twiggy представляет из себя парсер расширяющий modParser.
Twiggy перехватывает обработку twig тегов на странице.
Подробнее ознакомится с TWIG можно на официальном сайте и на сайте сообщества TWIG.

При установке пакета в контексте web создаются две настройки:
  • parser_class — класс парсера
  • parser_class_path — путь к классу парсера
Соответственно twiggy парсер используется только для данного контекста web.


настройки пакета

  • twiggy_extensions — список активных расширений через запятую, для подключения в Twiggy.
  • twiggy_path_extensions — путь для загрузки расширений Twiggy.
  • twiggy_path_templates — путь для загрузки шаблонов Twiggy.
  • sandbox — разрешить режим песочницы, при подключении шаблона в Twiggy.
настройки twig

Настройки twig вынесены в отдельную секцию. Доступны следующие настройки:
  • debug: При установке в true, генерируемые шаблоны имеют__toString() метод, который можно использовать для отображения сгенерированных узлов (по умолчанию false).
  • charset: Кодировка, используемая в шаблонах (по умолчанию в UTF-8)
  • base_template_class: Шаблон базового класса, который используют для сгенерированных шаблонов (по умолчанию Twig_Template).
  • cache: Абсолютный путь, где хранятся скомпилированные шаблоны или false чтобы отключить кэширование (который по умолчанию).
  • auto_reload: При разработке с Twig, полезно повторно компилировать шаблон при изменении кода-исходника. Если вы не установили значение опции auto_reload, то она будет определена автоматически на основании переменной debug.
  • strict_variables: Если установлено false, Twig будет по умолчанию игнорировать недействительные переменные (переменные и или атрибуты/методы, которые не существуют) и заменять их значением null. Когда устанавлено true, Twig генерирует исключение (по умолчанию false).
  • autoescape: Если установить true, авто-сохранение будет разрешено по умолчанию для всех шаблонов (по умолчанию true). Начиная с Twig 1.8, вы можете выбрать какую методику сохранения использовать (html, js, false для блокировки). Начиная с Twig 1.9, вы можете выбрать какую методику сохранения использовать (css, url, html_attr, или обратный вызов PHP, который берет шаблон “имя файла” и должен вернуть методику сохранения для использования — обратный вызов не может быть названием функции, чтобы избежать конфликта (коллизии) со встроенными методами сохранения. optimizations: Флаг, который указывает, какие оптимизации применять (по умолчанию -1 — все оптимизации разрешены; установите его на 0 для отключения).
настройки sandbox

Режиме песочницы. Добавляет изолированный режим в среду Twig, что делает его безопасным для оценки ненадежного кода.

  • sandbox_tags — список разрешенных тэгов через запятую, для подключения в режиме песочницы.
  • sandbox_filters — список разрешенных фильтров через запятую, для подключения в режиме песочницы.
  • sandbox_methods — строка, закодированная в JSON, с разрешенными методами для подключения в режиме песочницы.
  • sandbox_properties — строка, закодированная в JSON, с разрешенными свойствами для подключения в режиме песочницы.
  • sandbox_functions — Список разрешенных функций через запятую, для подключения в режиме песочницы.
расширения twig

По умолчанию twig запускается со следующими расширениями
  • Twig_Extension_Core — определяет все основные возможности Twig.
  • Twig_Extension_Escaper — добавляет автоматический вывод данных-сохранение, а также возможность сохранить/пропустить блоки кода
  • Twig_Extension_Optimizer — оптимизирует древо узлов перед компиляцией

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

— файл расширения должен лежать по пути указанному в path_extensions
— имя класса расширения соответствует TwiggyExtensionимя
имя расширения должно быть указано в настройке extensions

шаблоны twig

Twiggy автоматически подгружает шаблоны с таблицы modTemplate, а так же файловые шаблоны из папки указанной в настройке path_templates
Имена шаблонов соответствуют их названиям, например

создадим шаблон base в MODX
<!DOCTYPE html> 
<html>
    <head>
        {% block head %}
            <link rel="stylesheet" href="style.css" />
            <title>{% block title %}{% endblock %} - Мой сайт</title>
        {% endblock %}
    </head>
    <body>
        <div id="content">{% block content %}{% endblock %}</div>
        <div id="footer">
            {% block footer %}
                © Copyright 2013 <a href="http://example.com/">Вы</a>.
            {% endblock %}
        </div>
    </body>
</html>
создадим расширяющий шаблон
{% extends "base" %}

{% block title %}Главная{% endblock %}
{% block head %}
    {{ parent() }}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}
{% block content %}
    <h1>Главная</h1>
    <p class="important">
        Приветсвую на своем потрясном сайте!
    </p>
{% endblock %}

доступные переменные
Доступны следующие глобальные переменные
  • get — $_GET
  • post — $_POST
  • session — $_SESSION
  • cookie — $_COOKIE
  • request — $_REQUEST
  • files — $_FILES
  • server — $_SERVER
  • modx — $modx
  • pls — массив доступных плейсходеров

расширения Tools
Для большего удобства написано небольшое расширения Tools github.com/vgrish/twiggy/blob/master/core/components/twiggy/elements/extensions/tools.class.php

там описаны основные функции и фильтры для комфортной работы с MODX api.
Ниже несколько примеров:

вывести заголовок ресурса
{{ modx.resource.pagetitle }}
//или
{{ resource('pagetitle') }}

получить объект modUserProfile и преобразовать в json
{{ getObject('modUserProfile', {'email':'admin@vgrish.ru'})|toJson }}

вывести почту авторизованного пользователя
{{ profile('email') }}

подсчитать кол-во modUserProfile
{{ getCount('modUserProfile') }}

вывести чанк
{{ chunk('@INLINE {{ name }} - {{ fio }}', data) }}

обратится к процессору и вывести результат работы
{% set response = processor('mgr/valute/getlist',{'ns':'currencyrate', 'sortdir':'asc'}) %}
{# { dump(response) }#}
{% for result in response.response.results %}
    <li>
        {{ result.name }}
    </li>
{% endfor %}

лексиконы
{{ loadLexicon('ru:core:default') }}
{{ _('access_denied') }}
и тд. Если вам интересны задавайте вопросы.

расширение Cache
Написано небольшое расширение для кэширования секций Cache github.com/vgrish/twiggy/blob/master/core/components/twiggy/elements/extensions/cache.class.php

пример, указываем ключ кэша и время
{% cache 'neighbors' 3000 %}
    {{ snippet('pdoNeighbors') }}
{% endcache %}

расширение DebugBar
phpdebugbar.com/
пример вывода
{% if hasSessionContext('mgr') %}

{{ dbgHead() }}
{{ dbgMessage(array) }}
{{ dbgRender() }}

{% endif %}


уницикация
Для большей унификации описаны методы getChunk и parseChunk аналогичные методам из пакета pdoTools Василия Наумкина.

$Twiggy->getChunk('twig', $row);

Код на github, создавайте isuue
Готовый пакет пока можно установить из моего репозитория rstore.pro/extras/

PS. Не рекомендую к установке на рабочие проекты
Чтобы отключить работу Twiggy парсера достаточно удалить настройки из контекста
Володя
04 января 2016, 10:40
modx.pro
8 354
+3
Поблагодарить автора Отправить деньги

Комментарии: 43

Григорий Коленько
04 января 2016, 17:46
+1
Twig уже пол года использую на фронте, шаблон собираю gulp'ом. Если кому интересно, могу в ближайший месяц статью написать как использовать это все в modx.
Вообще сборка шаблона на сервере, по-моему большая ошибка. Зачем сервер загружать тем, что должно делаться во фронте 1 раз при сборке проекта? А так каждый сброс кэша — сборка шаблона. Практически отказался по этой причине от Fenom (пусть он и очень быстрый), использую только для удобства написания условий.

Это мое мнение при всем уважении к Володе и Василию :)
    Володя
    04 января 2016, 17:54
    0
    каждому свое…
    По поводу вашей реализации с интересном бы прочел.
    Спасибо!
      Павел Гвоздь
      04 января 2016, 20:29
      0
      Тоже с радостью прочту статью. Ждём. :)
      Алексей
      05 января 2016, 09:12
      +1
      Подскажите, а с кэшированием тут дела обстоят лучше чем в решении fenom+modx?
        Володя
        05 января 2016, 10:59
        0
        Нельзя сказать лучше или хуже, я бы сказал одинаково.
        И тут и там компилируется шаблон/код и хранить его явно в html нет никакого смысла, иначе бы все это отрабатывало один раз, при первичной загрузке.

        Вы можете использовать кэширование секций, указав ключ кэша и время
        {% cache 'neighbors' 3000 %}
            {{ snippet('pdoNeighbors') }}
        {% endcache %}
        данная секция сохранится в html
          Fi1osof
          05 января 2016, 11:43
          0
          Второй вопрос как раз и задал человек комментарием выше. И совершенно не без основательно. Вот мы смотрим кеш документа с твоим шаблоном:
          '_content' => '{% extends "BaseTemplate" %}
          
          {% block title %}Главная{% endblock %}
          {% block head %}
              {{ parent() }}
              <style type="text/css">
                  .important { color: #336699; }
              </style>
          {% endblock %}
          {% block content %}
              <h1>Главная</h1>
              <p class="important">
                  Приветсвую на своем потрясном сайте!
              </p>
          {% endblock %}',
          Он же не скомпилированный. Кеширование отдыхает тогда в принципе. Это то, что было долгое время в самом MODX (я раньше не однократно писал про его проблемы, из-за того, что он даже кешируемые теги в кеш пишет как есть, и потом все равно каждый раз реплейс делает), и что в MODX наконец-то поправилось (теперь он в кеш пишет сразу конечный HTML из кешируемых элементов), и теперь ты это достижение ломаешь. Шаблоны будут чуть более гибкие, но зато более тормознутые.

          И тут и там компилируется шаблон/код и хранить его явно в html нет никакого смысла, иначе бы все это отрабатывало один раз, при первичной загрузке.
          Хранить в конечном html очень даже есть смысл, в этом и есть смысл кеширования ресурсов. А вот то, что иначе не будет отрабатываться каждый раз — так вот для этого и были придуманы не кешируемые MODX-теги. Напиши один сниппет вида [[!twig?tpl=`some_tpl`]] и все. И где надо некешируемые блоки вставлять — там его и прописывать в шаблонах.
          Еще раз: в MODX с точки зрения шаблонизации только два минуса:
          1. нет компиляции в нормальный php (чтобы логика была)
          2. нет расширения шаблонов.
          В остальном она довольно продвинутая (особенно крут вложенный парсинг).
          Ты добавляешь расширяемости и логики, но ломаешь родное кеширование.
            Володя
            05 января 2016, 17:47
            0
            спасибо! Есть над чем подумать.
              Fi1osof
              05 января 2016, 17:59
              0
              Не за что!

              Вот это еще глянь, должно пригодиться: modx.pro/help/7278/#comment-52671
                Володя
                03 февраля 2016, 09:58
                0
                Я чет так подумал, так если положим в кэш конечный html — то какой от этого смысл?
                Тогда изначальна вся затея ни к чему. Вся гибкость шаблонизатора пропадает.
                Или я не прав?
                  Fi1osof
                  03 февраля 2016, 10:03
                  0
                  Таки да. При неправильном подходе. Я-то не раз уже говорил про необходимость наличия маленького сниппета для некешируемого вызова шаблончиков. У нас есть такой сниппет. Вызов простой [[!smarty?tpl=`inc/some.tpl`]]
                  При таком подходе и общий шаблон кешируется, и есть гибкость на динамических блоках.
                    Володя
                    03 февраля 2016, 10:20
                    0
                    понял, спасибо!
                      Fi1osof
                      03 февраля 2016, 11:09
                      0
                      Не за что!
                        Володя
                        07 февраля 2016, 21:02
                        0
                        Николай привет.
                        Опять к вопросу о сниппете.
                        Создал ресурс, вызвал сниппет
                        [[!smarty?tpl=`tpl/test.tpl`]]
                        смотрю в кэш ресурса — логично там именно этот вызов сниппета.
                        Вопрос все тот же — чем это помогает кэшированию? В чем фишка я не пойму.
                        Спасибо!
                          Fi1osof
                          07 февраля 2016, 21:06
                          -1
                          Привет.

                          Чтобы это помогало кешированию, надо вызов делать кешируемым. [[smarty?tpl=`tpl/test.tpl`]]

                          А некешируемые вызовы — это уже внутри самого шаблона, к примеру
                          <html>
                          	<head></head>
                          	<body>
                          		<header>
                          			[[smarty?tpl=`inc/menu.tpl`]]
                          			[[!smarty?tpl=`inc/login.tpl`]]
                          		</header>
                          		
                          		<div>
                          			[[*content]]
                          		</div>
                          	</body>
                          </html>
                          Здесь разъяснять же не надо?
                          Володя
                          07 февраля 2016, 21:14
                          0
                          то есть такую конструкцию имеет смысл применять только на блоках где не важна динамика. Спасибо за разьяснения, теперь окончательно ясно.
                          Fi1osof
                          07 февраля 2016, 21:21
                          -1
                          Так для этого кеширование в шаблонах (и кеширование элементов) и придумано. Конечно можешь весь код сразу вставить в шаблон как есть и там уже указать некешируемые элементы, но это сразу же дико будет походить на стандартные чанки. А общий элемент [[smarty?tpl=`tpl/test.tpl`]] для того и пишется, чтобы в базовом шаблоне можно было прописать расширение.

                          Вот у тебя MODX-шаблон «Основной»:
                          [[smarty?tpl=`tpl/index.tpl`]]

                          В tpl/index.tpl прописано:
                          <html>
                          	<head></head>
                          	<body>
                          		<header>
                          			[[smarty?tpl=`inc/menu.tpl`]]
                          			[[!smarty?tpl=`inc/login.tpl`]]
                          		</header>
                          		
                          		<div>
                          			{block content}[[*content]]{/block}
                          		</div>
                          	</body>
                          </html>
                          А вот у тебя MODX-шаблон «Главная страница»:
                          [[smarty?tpl=`tpl/mainpage.tpl`]]

                          В tpl/mainpage.tpl прописано:
                          {extends "tpl/index.tpl"}
                          {block content prepend}
                          	{include "inc/slider.tpl"}
                          {/block}
                          На выходе все кроме [[!smarty?tpl=`inc/login.tpl`]] у тебя будет кешируемым, на главной помимо контента еще и слайдер появится, и не придется дублировать код в MODX-шаблонах.
      Fi1osof
      05 января 2016, 11:23
      0
      Владимир, сам знаешь, я приветствую начинания в области шаблонизации, но сорри, некоторые вопросы буду не очень удобные задавать. Просто в свое время и я шишек набил с подобными компонентами, так что есть от чего отталкиваться.

      Вопрос первый: Зачем тебе вот это? Оно итак в modResponse::outputContent() отрабатывается. (на самом деле я предполагаю зачем оно тебе, но тут несколько вариантов, так что хотелось бы именно твой вариант услышать).
        Василий Наумкин
        05 января 2016, 11:59
        0
        Затем же, зачем оно же и в pdoTools, у которого обработка тегов Fenom запускается после process() самого документа.

        И если включена настройка pdotools_fenom_parser и сниппеты, регистрирующие скрипты и стили, вызываются прямо в контенте документа, то файлы от них в эти массивы они уже не попадают и приходится добавлять их вручную. Вот тут багрепорт.
          Fi1osof
          05 января 2016, 12:16
          0
          Такого ответа я и ожидал. Но вы изначально все не правильно делали. Эти скрипты известны документу еще на уровне получения его из кеша. Все, что вам нужно было — это плагин навесить на правильное событие и присвоить документу эти данные. И все бы у вас было ОК.
          Почему я про этот кусок кода спросил? Во-первых, этот метод парсера в процессе отработки документам может быть вызван не один раз. Во-вторых, в разные стадии вызова его в массивах этих могут содержаться разные наборы скриптов (что не страшно, конечно же, ибо все равно они будут в шаблон подставлены только в одном месте, но как минимум бессмысленно).
            Василий Наумкин
            05 января 2016, 12:25
            0
            Ты чего меня на вы-то? Вроде уже лично познакомились.

            А вообще, тут всё просто. Без этой правки скрипты и стили из кэшируемых сниппетов, вызванных через Fenom, не добавлялись на страницу. А с ней — добавляются.

            Сделать так мне показалось просто и логично, но если ты считаешь, что MODX нужно делать дополнительный вызов плагина для этой операции — шли PR на GitHub, добавим.
              Fi1osof
              05 января 2016, 12:56
              0
              Да не, вы — это я во множественном числе. Сначала ты, потом Володя, до него еще кто-нибудь (я же не очень пристально за вашими компонентами следил и не знаю кто когда еще подобный трюк выполнял). Это вот сейчас я стал больше интересоваться унификацией, вот и поглядываю иногда :)

              А вообще, тут всё просто. Без этой правки скрипты и стили из кэшируемых сниппетов, вызванных через Fenom, не добавлялись на страницу. А с ней — добавляются.
              Тут ответ однозначный: где-то неверная последовательность вызова/вывода. Ты четко знаешь когда бага возникает. Если не лень, создай тестовый сайт с этой багой (феном + минифи), закомментируй этот свой хак и пришли доступ, я посмотрю. Уверен, найду суть проблемы.
                Василий Наумкин
                05 января 2016, 13:09
                0
                Насколько я вижу, половина логики Twiggy скопирована из pdoTools, поэтому и отвечаю на твои вопросы =)

                Тут ответ однозначный: где-то неверная последовательность вызова/вывода.
                Может быть.

                Но по моему, дело в том, что теги Fenom на странице отрабатывают после процессинга документа через MODX, и данные кэшированных сниппетов не попадают в массивы скриптов и стилей. То есть, сниппет кэшируется, а то что он регистрировал в первый раз — нет.

                Вот тестовый сайт:
                чанк с кэшированным вызовом MinifyX
                класс pdoParser с закоментированным добавлением скриптов и стилей после обработки тегов Fenom

                Логин s3914
                Пароль UAChpcjgpO9r
                  Fi1osof
                  05 января 2016, 13:17
                  0
                  Насколько я вижу, половина логики Twiggy скопирована из pdoTools, поэтому и отвечаю на твои вопросы =)
                  Я так и понял :) Предполагаю, что тебе даже не очень-то и нравится такая объемная копируемость :)

                  Я пока не буду ничего отвечать. Мысли есть, но нужны факты. Щас поковыряю сайт и по результатам отпишусь.
                    Василий Наумкин
                    05 января 2016, 13:25
                    0
                    На мой взгляд, если приходится много чего-то копировать, то лучше наследовать и расширять.

                    Тем более, что технически ничего не мешает написать сторонний парсер, который будет наследовать pdoTools со всеми его возможностями. А pdoParser просто отключить при установке и возвращать обратно при удалении.

                    Но это моё сугубо личное мнение, никому не навязываю.
                      Fi1osof
                      05 января 2016, 15:00
                      +1
                      Да не, все верно. Я вообще отметил набирающую оборот тенденцию: много кто стал просто переделывать чужие пакеты. То есть не создавать что-то новое, а именно переделывать. ИМХО или PR, или что-то принципиально новое. К примеру, как ты меня когда-то обвинил в том, что я modSociety запулил, хотя есть Articles. Да, эти решения примерно направлены на одно и то же, но они принципиально разные. Это не копии, это абсолютно разные решения. А сейчас как делают? Скопируют Articles, назовут по другому, и скажут, что вот тут есть принципиальные улучшения. Ну ты понял.
                    Fi1osof
                    05 января 2016, 14:41
                    3
                    +6
                    Сорри за долгий ответ, отвлекся.

                    Но по моему, дело в том, что теги Fenom на странице отрабатывают после процессинга документа
                    Все верно. Из-за этого и была проблема. Дело в том, что $modx->regClientStartupScript() и подобные методы работают со свойствами самого $modx, а вот при сохранении кеша используются свойства самого ресурса. А так, как в отработанных уже после процессинга тегах выполняется типа $modx->regClientStartupScript() (который устанавливает свойства для $modx, но не устанавливает их для $modx->resource), то при генерации кеша документа этих скриптов в кеше просто нет. joxi.ru/4Ak3wb9tMX8nGA
                    Решение: пишем плагин на событие OnBeforeSaveWebPageCache, простейший вид:
                    $modx->resource->_jscripts = $modx->jscripts;
                    $modx->resource->_sjscripts = $modx->sjscripts;
                    $modx->resource->_loadedjscripts = $modx->loadedjscripts;
                    И тогда при генерации кеша документа будут сохранены все скрипты. joxi.ru/LmGVQx0uRJN1Xr
                    При чем это будет выполняться только при первом заходе на страницу. Когда документ уже закеширован будет, это не будет выполняться.

                    UPD: Может даже имеет смысл это в ядро запулить (то есть код кешманагера поправить), так как очень похоже на багу самого MODX-а. Какая-то глупость в двух отдельных сущностях хранить эти переменные и создавать/получать в разных местах на разных этапах.
                      Василий Наумкин
                      05 января 2016, 15:04
                      +1
                      Отличный анализ, спасибо!

                      Думаю, ничего страшного не случится, если я пока оставлю всё как есть.
                        Fi1osof
                        05 января 2016, 15:14
                        0
                        Не за что!

                        Конечно нет))
            Алексей
            23 января 2016, 09:24
            0
            Николай, подскажите, в Вашнй реализации шаблонизатора для modx (modxSmarty) с кэшированием все обстоит лучше?
            PS: разрабатываю новый сайт, и вопрос опять встал ребром — какой шаблонизатор использовать. Благо для modx уже есть выбор-)
              Fi1osof
              23 января 2016, 09:41
              0
              Лучше. Сейчас и в самом MODX с кешированием все лучше стало, хотя бы потому что теперь MODX результат кешируемых элементов в кеш сохраняет как готовый HTML (раньше он этого не делал), из-за чего сейчас у меня даже отпадает необходимость использования компонента phpTemplates. Теперь я просто в обычный MODX-шаблон прописываю, например, [[smarty?tpl=`tpl/mainpage.tpl`]] и все ОК.
                Алексей
                23 января 2016, 10:04
                0
                Замечательно! было бы классно сделать табличку сравнения быстродействия реализации 3 шаблонизаторов для модкс (fenom, twigg,smarty), в связи с чем вопрос: как правильно написать данный тест на modxSmarty?
                  Fi1osof
                  23 января 2016, 10:44
                  +1
                  Тестировал в консоли.

                  1. pdoResources
                  $output = $modx->runSnippet('pdoResources', array(
                      "parents"   => 7,
                      "limit"     => 4000,
                      "depth"     => 0,
                      "showLog"   => 0,
                      "tpl"       => '@INLINE {{+id}}-{{+menuindex}}-{{+createdon}}-{{+publishedon}}',
                  ));


                  2. Smarty + getdata-процессор.
                  В консоли:
                  $modx->invokeEvent('OnHandleRequest'); 
                  $modx->startTime = microtime(true);
                  $output = $modx->smarty->fetch('test/getdata.tpl');
                  Шаблон:
                  {$params = [
                      "limit" => 4000
                  ]}
                  
                  {processor action="web/getdata" ns="modxsite" params=$params assign=result}
                  
                  {foreach $result.object as $row}
                      <p>
                          {$row.id}-{$row.menuindex}-{$row.createdon}-{$row.publishedon}
                      </p>
                  {/foreach}


                  3. Smarty + чистый xPDO
                  В консоли:
                  $modx->invokeEvent('OnHandleRequest'); 
                  $modx->startTime = microtime(true);
                  $output = $modx->smarty->fetch('test/pure.tpl');

                  Шаблон:
                  {$q = $modx->newQuery('modResource')}
                  {$ok = $q->select(['modResource.*'])}
                  {$ok = $q->limit(4000)}
                  {$s = $q->prepare()}
                  {$ok = $s->execute()}
                  
                  {while $row = $s->fetch(2)}
                      <p>
                          {$row.id}-{$row.menuindex}-{$row.createdon}-{$row.publishedon}
                      </p>
                  {/while}


                  Разница очевидна.

                  P.S. наверняка феном + чистый xPDO тоже хороший результат покажет.
                    Василий Наумкин
                    24 января 2016, 12:54
                    0
                    наверняка феном + чистый xPDO тоже хороший результат покажет.
                    Проверил не совсем в чистом виде, а вызовом через сниппет:
                    <?php
                    $pdo = $modx->getService('pdoTools');
                    
                    return $pdo->getChunk($tpl);

                    При пустом шаблоне документа:
                    [[!Fenom?&tpl=`@INLINE
                    	{var $resources = $_modx->getResources([], ['limit' => 4000])}
                    	{foreach $resources as $resource}
                    		<p>{$resource.id} - {$resource.menuindex} - {$resource.createdon} - {$resource.publishedon}</p>
                    	{/foreach}
                    	<pre>{$_modx->getInfo()}</pre>
                    `]]
                    

                    Результат:
                    queries: 13
                    totalTime: 0.3718 s
                    queryTime: 0.0532 s
                    phpTime: 0.3186 s
                    source: database
                      Fi1osof
                      24 января 2016, 15:53
                      0
                      На сколько я понимаю, @INLINE у тебя все равно отрабатывается как чанк? То есть типа такого
                      $chunk = $modx->newObject('modChunk');
                      $chunk->code = $inline_code;
                      $output =  $chunk->process();
                      return $output;
                      Или я не прав? Если так, то все равно, хоть и не из базы данных, но все равно объект каждый раз создается. Так не может быстро работать. Вот если модифицировать в такое (упрощенно), то должно быстрее работать.
                      $output = '';
                      $chunk = $modx->newObject('modChunk');
                      while($row = $s->fetch(2)){
                      	$chunk->code = $inline_code;
                      	$output .=  $chunk->process();
                      }
                      return $output;
                        Василий Наумкин
                        24 января 2016, 15:58
                        +3
                        Все чанки кэшируются внутри pdoTools и стараются не выполняться через объекты. Там масса всяких оптимизаций.

                        Но и оверхеда всякого достаточно, хотя лично мне скорости вполне хватает, чтобы не морочиться дальше. Решение должно быть достаточно универсально и работать удобно из коробки, без танцев.

                        Сейчас заканчиваю один сайт, полностью построенный на Fenom и готовых дополнениях — все страницы открываются за 0.2 — 0.3 сек., может позже напишу заметку с подробностями.
                          Fi1osof
                          24 января 2016, 16:24
                          +2
                          Не, на счет адекватности задачам полностью согласен. В жизни выборка 4000 документов и набивка их в чанки крайне маловероятна. А на 10-20 документах разница практически не ощущаема и оверклокингом заниматься нет смысла.
                    Володя
                    05 февраля 2016, 22:47
                    0
                    в консоли сниппет pdoResources

                    gist.github.com/vgrish/8189582355782ec13394
                    $modx->switchContext('web');
                    $modx->invokeEvent('OnHandleRequest'); 
                    
                    if (!$twiggy = $modx->getService('twiggy', 'twiggy', $modx->getOption('twiggy_core_path', null, $modx->getOption('core_path') . 'components/twiggy/') . 'model/twiggy/')) {
                    	return 'Could not load twiggy class!';
                    }
                    
                    $tpl = '
                    {% set aaaa = snippet("!pdoResources", {
                            "parents":1,
                            "limit":4000,
                            "tpl": "@INLINE {{ pls[\"id\"] }}-{{ pls[\"menuindex\"] }}-{{ pls[\"createdon\"] }}-{{ pls[\"publishedon\"] }}"
                    }) %}
                    
                    {{ getInfo() }}';
                    
                    $output = $twiggy->process($tpl, array(), false);
                    
                    print_r($output);

                    totalTime: 1.3793 s
                    queryTime: 0.0526 s
                    phpTime: 1.3267 s
                    queries: 9
                    source: cache

                    в консоли xPDO
                    gist.github.com/vgrish/2530a0364bf49b05481f
                    $modx->switchContext('web');
                    $modx->invokeEvent('OnHandleRequest'); 
                    
                    if (!$twiggy = $modx->getService('twiggy', 'twiggy', $modx->getOption('twiggy_core_path', null, $modx->getOption('core_path') . 'components/twiggy/') . 'model/twiggy/')) {
                    	return 'Could not load twiggy class!';
                    }
                    
                    $tpl = "
                    {% set q = modx.newQuery('modResource') %}
                    {% set ok = q.select(['modResource.*']) %}
                    {% set ok = q.limit('4000') %}
                    {% set s = q.prepare() %}
                    {% set ok = s.execute() %}
                    {% for resource in s.fetchAll(2) %}
                        <p>{{ resource.id }} - {{ resource.menuindex }} - {{ resource.createdon }} - {{ resource.publishedon }}</p>
                           
                    {% endfor %}
                    {{ getInfo() }}
                    ";
                    
                    $output = $twiggy->process($tpl, array(), false);
                    
                    print_r($output);
                    totalTime: 0.1909 s
                    queryTime: 0.0011 s
                    phpTime: 0.1898 s
                    queries: 3
                    source: cache
              Сергей Шлоков
              18 февраля 2018, 11:28
              0
              Володь, ты забросил эту тему? На феноме работаешь?
                Володя
                18 февраля 2018, 11:42
                +2
                Давно забросил. Попробовав смарти, твиг, феном могу уверенно сказать что фен просто прекрасен.
                  Василий Наумкин
                  19 февраля 2018, 09:01
                  +1
                  Может, напишешь на досуге заметку со сравнением?

                  Думаю, не только мне будет интересно прочитать.
                    Володя
                    19 февраля 2018, 10:14
                    +1
                    Возможно напишу.
                Сергей Шлоков
                18 февраля 2018, 12:00
                -2
                Жаль. Феном конечно прекрасен, но на «коротких» дистанциях. А чуть дальше и он со своим односкобочным синтаксисом сдаётся перед специфическим механизмом парсинга MODX. Поэтому хочу попробовать Twig, чтобы забыть про подобные ошибки
                // Пример ошибки при выводе ресурса через функцию dump() из modHelpers.
                Unexpected token '<' in expression in e4d771b3eb4eed60131330f50f7a360d line 2, near '{<' <- there
                П.С. Подобные ошибки валятся и из некоторых других библиотек, с которыми я экспериментирую. Поэтому хотелось бы покончить с ними раз и навсегда. В других шаблонизаторах используется особый синтаксис типа {{ или {% или {!!. Что теоретически должно исключить данную проблему.

                П.П.С. А вообще, идея совмещать 2 механизма парсинга хреновая. Ни один нормально не работает. Это относится к любому стороннему шаблонизатору в MODX.
                  Володя
                  19 февраля 2018, 10:21
                  +1
                  Поэтому хочу попробовать Twig, чтобы забыть про подобные ошибки
                  Так попробуй!) Все познается в сравнении.
                  односкобочным синтаксисом сдаётся перед специфическим механизмом парсинга MODX
                  Мне односкобочный синтаксис очень люб. Гибкость, быстрота и легкая расширяемость феном — что еще нужно?
                  Прямых конкурентов я не вижу…

                  забыть про подобные ошибки
                  не сталкиваюсь с таким, потому и решать не приходилось.

                  Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                  43