[pdoTools] 2.5.0 - файловые элементы

Представляю вам новую версию с улучшенной поддержкой загрузки элементов из файлов.

Теперь из файлов можно грузить не только оформление, но и запускать PHP код. Это позволяет вынести в них почти все элементы системы: шаблоны, чанки, плагины и сниппеты.

Подробная документация, как обычно, вот здесь, а под катом список изменений

Все элементы по умолчанию загружаются из директории, указанной в системной настройке pdotools_elements_path, по умолчанию там
MODX_CORE_PATH . 'elements'
Если вы хотите использовать файловые элементы — то нужно создать её самостоятельно.

Дальше можно загружать сниппеты и чанки через методы pdoTools:
if ($pdoTools = $modx->getService('pdoTools')) {
    $chunk = $pdoTools->getChunk('@FILE chunks/my_chunk.tpl', array('placeholder' => 'value'));

    $snippet = $pdoTools->runSnippet('@FILE snippets/my_snippet.php', array('param' => 'value'));
}

Fenom может делать это двумя способами:
{$_modx->getChunk('@FILE chunks/my_chunk.tpl', ['placeholder' => 'value'])}
{'@FILE chunks/my_chunk.tpl' | chunk : ['placeholder' => 'value']}

{$_modx->runSnippet('@FILE snippets/my_snippet.php', ['param' => 'value'])}
{'@FILE snippets/my_snippet.php' | snippet : ['param' => 'value']}

Так как Fenom изначально рассчитан на работу с файловыми шаблонами, теперь можно использовать его родной провайдер файлов как file:
{include 'file:chunks/my_chunk.tpl'}
А расширение как и раньше, только с указанием file:
{extends 'file:chunks/my_chunk.tpl'}

{block 'myblock'}
    Hello world!
{/block}
Это рекомендуемый способ загрузки файлов из Fenom.

Обычные чанки, которые хранятся в БД, грузятся примерно так же:
{include 'my_chunk'}

Кэширование всех скомпилированных шаблонов включается настройкой pdotools_fenom_cache. Кэш обычных чанков из БД хранится с помощью MODX, а кэшем для file: рулит сам Fenom.

Именно поэтому для файлов в Fenom лучше использовать его собственные методы — он сможет проверить изменения и перегенерировать кэш без обращения к MODX.

Чтобы почистить этот кэш нужно удалить директорию core/cache/default/pdotools или сбросить весь кэш сайта.

Остальные изменения


— Добавлен вывод текущего лога в метод $_modx::getInfo(). Лучше использовать его с модификатором print:
{$_modx->getInfo() | print}
Полезно для отладки.

— Улучшена поддержка debugParser, добавлено логирование основных модификаторов.

— Улучшена загрузка моделей при вызове сниппетов. Теперь можно указывать префиксы.

Заключение


Хочу выразить благодарность за идею и направление реализации Сергею Шлокову.

Теперь с помощью pdoTools и Fenom можно вынести основные элементы в файлы, подключить к ним Git и применять изменения просто выгрузкой на сервер.

Например, создаём шаблон и назначаем его ресурсу. Внутрь пишем
{include 'file:templates/base.tpl'}
Нужно включить системную настройку pdotools_fenom_parser, чтобы Fenom обработал этот шаблон и загрузил его из файла. Дальше мы уже рулим всем оформлением прямо в этом файле.

Например, вот так:
<!doctype html>
<html lang="en">
<head>
    {include 'file:chunks/head.tpl'}
</head>
<body>
<div class="nav-container">
    <nav>
        {include 'file:chunks/header.tpl'}
    </nav>
</div>

<div class="main-container">
    {include 'file:chunks/slider.tpl'}
    {block 'content'}
    {/block}
</div>
{include 'file:chunks/footer.tpl'}
</body>
Эти чанки уже работают чисто из файлов, в БД MODX про них ничего нет. Внутри могут быть вызовы любых сниппетов и чанков системы, как файловых, так и обычных.

Более того, второй шаблон может расширять первый. Его тоже придётся создать в MODX, чтобы назначить ресурсам, а дальше:
{extends 'file:templates/base.tpl'}

{block 'content'}
    {$_modx->getInfo() | print}
{/block}
Расширяем первый шаблон и выводим в контенте информацию.

Обновлено 30.05.2016


Выложил версию 2.5.1-pl, в которой исправлено излишнее кэширование сниппетов.
Василий Наумкин
29 мая 2016, 03:44
modx.pro
16
9 131
+21

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

Роман
29 мая 2016, 18:17
0
Просто супер!!!
    Евгений Ка
    29 мая 2016, 23:08
    0
    Правильно ли я понимаю, что раньше вызов runSnippet был всегда некешированный?!
    Хотя странное спросил. Вроде как по логике runSnippet это системная функция.
    Александр Котлов
    29 мая 2016, 23:12
    0
    Сделал тестовый сайт, парсер вкючил, elements создал, там templates и в ней base.tpl
    получил
    [2016-05-29 23:07:33] (ERROR @ /home/s5520/www/core/components/pdotools/model/pdotools/pdotools.class.php : 944) Template templates/base.tpl not found in fca37e72e79b626b786a3b7dd8147b57 line 1, near '{include 'file:templates/base.tpl'' <- there
    Попробовал на другом — тоже самое. Кто-нибудь проверял уже? Норм работает? Кавычка смущает в логе лишняя…
      Василий Наумкин
      30 мая 2016, 06:26
      0
      elements должен быть внутри core, по умолчанию. А у тебя было вот так:


      Перенёс директорию, заработало.
        Александр Котлов
        30 мая 2016, 10:37
        0
        Василий, спасибо!
          Владимир
          03 июня 2016, 07:54
          0
          Василий, скажи, а не уместен ли теперь новый источник файлов с путем core/elements/ устанавливаемый с pdoTools, типа pdoToolsStaticElements?
            Василий Наумкин
            03 июня 2016, 07:57
            +1
            Неа, источник файлов точно не нужен.

            Да и не советую устанавливать что-то по умолчанию не в components.
              Владимир
              03 июня 2016, 08:07
              0
              Ок, спасибо. Перенес в core/components/elements
              В админке так проще искать новые статичные файлы, с источником ))
                Василий Наумкин
                03 июня 2016, 10:06
                +1
                Я имел в виду, что разработчики MODX сильно не одобряют, когда компонент что-то ставит не в components.

                Например, меня прям отдельно просили убрать из pdoTools классы, которые копировались в core/model/modx.

                А на своём-то сайте ты можешь делать что хочешь, и хранить шаблоны где угодно.
        Paul B.
        30 мая 2016, 04:14
        0
        Вот капец! А я только соорудил «костыли» с помощью какого-то старинного костыля для пдотулс, чтобы хоть частично вынести все чанки и шаблоны через чанки. Но тут вышло это дополнение)))
        Спасибо, очень крутое!
          Klike
          30 мая 2016, 12:26
          1
          0
          del
          Klike
          30 мая 2016, 12:26
          0
          Внимание! После обновления советую проверить кэшированные вызовы {$_modx->runSnippet('Сниппет')} в чанках оформления результатов.
          Василий, на сайте используется несколько вызовов pdoResources, в первом чанк используется обычный, а в других – INLINE. Оба вызова кэшированные, и первый чанк в итоге подставляется в остальные. Если первый вызов сделать некэшированныем, то всё хорошо вроде. Теперь нужно всегда некэшированными сниппеты вызывать? А на скорости это разве не отразится?
            Василий Наумкин
            30 мая 2016, 12:27
            +1
            Это ошибка, только что выложил исправление — обновись, почисти кэш и проверяй.
              Klike
              30 мая 2016, 12:29
              0
              Спасибо, Василий! Теперь всё хорошо)
            Семён Кудрявцев
            30 мая 2016, 23:05
            0
            Крутой апгрейд pdoTools! Спасибо автору.
            И походу вопрос — Коснулось ли это параметров сниппетов? ну например pdoResources в параметре tpl вызвать чанк, который лежит в файле или по-старинке через параметр tplPath? И у меня почему-то перестал работать параметр tpl c @INLINE, у кого-то были такие проблемы?
            Семён Кудрявцев
            31 мая 2016, 07:19
            0
            Вчера поздно писал — мозг уже плохо формулировал мысли — сам сегодня перечитал свой комментарий и не совсем понял о чём там — суть хотел передать следующую — в сниппетах pdoTools можно писать tpl параметр через @FILE, который по-умолчанию /assets/elements/chunks/ — так может его теперь тоже core/elements/ сделать — место очень удобное выбрано близко от корня и закрыто как и ядро, да и при написании сниппетов не придётся постоянно параметр tplPath указывать.
            Семён Кудрявцев
            01 июня 2016, 22:43
            0
            Не могу нарадоваться тому что теперь все проекты можно разрабатывать в любимой IDE да ещё и с Fenom-ом, и тут меня посетила давняя мысль — в компоненте modxSmarty с которого я сейчас по-тихоньку слезаю, автором была заявлена очень интересная фича — когда ты залогинен в контексте mgr системная настройка с путём ко всем шаблонам могла быть изменена только для тебя — это бы дало возможность дорабатывать страницы, редизайнить их и экспериментировать на живом проекте и с живыми данными, но как бы со своим оформлением, в моей работе это очень актуальный вопрос — клиенты просят побыстрее запустить сайт и потом походу его дорабатывать, но на живом сайте вести доработки, особенно визуальные, которые надо тестить постоянно не очень то удобно, да и пользователям видеть эти полу-доработки ни к чему. В MODX есть классная штука, что, будучи авторизованным в mgr можно смотреть ещё не опубликованные ресурсы, но если шаблоны для этих ресурсов содержат хоть сколько нибудь сложную структуру с вызовами кучи сниппетов — это надо постоянно везде указывать параметры типа showUnpublished, а они есть не у всех сниппетов. Так вот к чему я это всё — было бы круто выставить допустим админу настройку pdotools_elements_path с другим путем отличным от общих шаблонов и если он авторизован в mgr то ему показывать шаблоны из этого пути, давая возможность параллельно вести доработку проекта. Что скажете? Вообще кому нибудь ещё интересна и полезна такая штука?
              Василий Наумкин
              02 июня 2016, 05:09
              +1
              Скажу что все файлы грузятся из пути, указанного в pdotools_elements_path. Это системная настройка, которая перекрывается настройками пользователя.

              Осталось сложить 2 + 2.
                Семён Кудрявцев
                02 июня 2016, 07:22
                0
                Работает))
                  Василий Наумкин
                  02 июня 2016, 07:31
                  +2
                  Может, юзер должен быть авторизован в контексте, чтобы применялись его настройки, как думаешь?
                    Семён Кудрявцев
                    02 июня 2016, 07:34
                    0
                    Да, Василий, беру слова обратно — всё работает как часы. Спасибо за столь ранний ответ.
              Руслан Кундиус
              02 июня 2016, 15:53
              +1
              Не уверен с какой версии, но появилась следующая проблема: если на странице два(и более) одинаковых сниппета с разными наборами параметров, во всех будет использован первый набор. Вот пример (второй блок должен быть желтым).

              Насколько я понимаю, здесь ключом является только название сниппета, без параметров, и все последующие наборы игнорируются.
              Семён Лобачевский
              05 июня 2016, 12:12
              0
              А если сравнивать скорость работы через хранение в файлах или в базе, где выше?
                Василий Наумкин
                05 июня 2016, 12:25
                +1
                Не знаю.

                Попробуй сравнить самостоятельно и рассказать про это нам.
                Eugene Generalov
                06 июня 2016, 12:29
                0
                Отлично! Попробуем!
                  Юрий
                  06 июня 2016, 22:56
                  0
                  У меня ядро вынесено за пределы корневого web-каталога. При этом при работе pdoTools в корневом каталоге создается директория путь_до_ядра/cache/default/pdotools/file, согласно строке 33 файла _fenom.php

                  pdoTools 2.5.2
                  MODX 2.5.0
                  PHP 7.0.7
                  Klike
                  05 июля 2016, 18:06
                  0
                  Василий, подскажи, пожалуйста, как выводить плейсхолдер некэшированным, по документации не нашел, может плохо искал.
                  Добавил кастомное поле даты в свойства товара, в первый раз выводит правильно, обновляю страницу – неправильно)
                  Код:
                  {'datestart'|placeholder} | {$_modx->getPlaceholder('datestart')} | {$_pls["datestart"]}
                  Результат:
                  В первый раз:

                  После обновления страницы:
                    Василий Наумкин
                    06 июля 2016, 04:42
                    0
                    Выглядит как версия miniShop2.4-beta2, а не rc.
                      Klike
                      06 июля 2016, 05:42
                      0
                      miniShop2.2.0-pl2))
                        Василий Наумкин
                        06 июля 2016, 05:45
                        +1
                        Еще лучше. Тогда, наверное, только делать страницу некэшированной.
                          Klike
                          06 июля 2016, 05:50
                          0
                          Да, некэшированная страница помогла, но так быстрее загружается:
                          [[+datestart:strtotime:date=`%d %b`]]

                          Спасибо, Василий!
                    Alexander V
                    10 июля 2016, 22:57
                    0
                    Вот такая конструкция в чанке почему-то не сработала. Всё отображается, как надо, но по ссылке logout и авторизации просто обновляется страница. При этом стандартный вызов работает нормально.
                    {$_modx->runSnippet('!HybridAuth', [
                    'providers' => 'yandex,google'
                    'groups' => 'Users:1'
                    ])}
                      Григорий Коленько
                      09 августа 2016, 13:16
                      0
                      В стандартном модификаторе fuzzydate есть строки
                      if ($time >= strtotime('today')) {
                                          $output = $modx->lexicon('today_at', array('time' => strftime('%I:%M %p', $time)));
                                      } elseif ($time >= strtotime('yesterday')) {
                                          $output = $modx->lexicon('yesterday_at', array('time' => strftime('%I:%M %p', $time)));
                                      } else {
                                          $output = strftime($format, $time);
                                      }
                      Они выводят следующее, если дата публикации, к примеру 00:13, то получим: «сегодня в 12:13»
                      Т.е. пользователя это может ввести в заблуждение по поводу даты публикации. Так задумывалось?
                      Не было бы вернее заменить %I на %k, чтобы вывело «сегодня в 0:13»?
                      Или я что-то упустил
                        TITAN-UZ
                        02 сентября 2016, 22:47
                        0
                        Как кэшироват вызов сниппета
                        {$_modx->runSnippet('@FILE snippets/game.php', ['param' => 'value'])}

                        Viktor
                        18 января 2018, 00:22
                        0
                        Можно ли закэшировать такой чанк? Кучу запросов к базе делает. Как вообще лучше писать сложные чанки с многими условиями, чтобы кучу чанков не плодить?
                        {include 'file:chunks/Cars.tpl' $inTextCarType='limo' $limit='0'}
                        Cars.tpl:
                        {if $limit != null}
                            {var $limit = $limit}
                            {else}
                            {var $limit = 4}
                        {/if}
                        {if $inTextCarType?}
                            {switch $inTextCarType}
                                {case 'limo'}
                                    {var $catalogID = 12}
                                {case 'sedani'}
                                    {var $catalogID = 9}
                                {case 'dzhipi'}
                                    {var $catalogID = 10}
                                {case 'retro'}
                                    {var $catalogID = 11}
                                {case 'mikroBus'}
                                    {var $catalogID = 134}
                            {/switch}
                            
                            {else}
                            
                            {var $catalogID = $_modx->resource.parent}
                            {var $resourcesNeeded = -$_modx->resource.id}
                            {switch $catalogID}
                                {case 12}
                                    {var $header = '<div class="headline"><h3>Другие популярные <a href="'~$catalogID|url~'">лимузины</a></h3></div>'}
                                {case 9}
                                    {var $header = '<div class="headline"><h3>Другие популярные <a href="'~$catalogID|url~'">седаны</a></h3></div>'}
                                {case 10}
                                    {var $header = '<div class="headline"><h3>Другие популярные <a href="'~$catalogID|url~'">джипы</a></h3></div>'}
                                {case 11}
                                    {var $header = '<div class="headline"><h3>Другие популярные <a href="'~$catalogID|url~'">ретро авто</a></h3></div>'}
                                {case 134}
                                    {var $header = '<div class="headline"><h3>Другие популярные <a href="'~$catalogID|url~'">микроавтобусы</a></h3></div>'}
                                {case default}
                                    {var $header = '<div class="headline"><h3>Популярные <a href="'~3|url~'">авто</a></h3></div>'}
                                    {var $catalogID = '9,10,11,12,134'}
                                    {var $resourcesNeeded = '13,27,26,25'}
                            {/switch}
                        {/if}
                        
                        
                        {'pdoResources' | snippet : [
                            'tplWrapper'=>'@FILE chunks/CarsWrapperTpl.tpl',
                            'tpl'=>'@FILE chunks/CarTpl.tpl',
                            'parents'=>$catalogID,
                            'resources'=>$resourcesNeeded,
                            'header'=>$header,
                            'inTextCarType'=>$inTextCarType,
                            'limit'=>$limit,
                            'sortby'=>'menuindex',
                        ]}
                          Viktor
                          23 января 2018, 20:50
                          0
                          выяснил, что передача этой переменной все время генерирует дополнительные запросы к БД:
                          {include 'file:chunks/Cars.tpl' $inTextCarType='sedani'}
                          {'pdoResources' | snippet : [
                              'tplWrapper'=>'@FILE chunks/CarsWrapperTpl.tpl',
                              'tpl'=>'@FILE chunks/CarTpl.tpl',
                              'inTextCarType'=>$inTextCarType,
                          ]}
                          почему так происходит?
                            Viktor
                            24 января 2018, 22:54
                            0
                            del
                          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                          46