[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
16
4 679
+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
      Спасибо, Василий! Теперь всё хорошо)
Sem
Sem
30 мая 2016, 23:05
0
Крутой апгрейд pdoTools! Спасибо автору.
И походу вопрос — Коснулось ли это параметров сниппетов? ну например pdoResources в параметре tpl вызвать чанк, который лежит в файле или по-старинке через параметр tplPath? И у меня почему-то перестал работать параметр tpl c @INLINE, у кого-то были такие проблемы?
    Sem
    Sem
    30 мая 2016, 23:24
    0
    C @INLINE разобрался — руки мои кривые.
Sem
Sem
31 мая 2016, 07:19
0
Вчера поздно писал — мозг уже плохо формулировал мысли — сам сегодня перечитал свой комментарий и не совсем понял о чём там — суть хотел передать следующую — в сниппетах pdoTools можно писать tpl параметр через @FILE, который по-умолчанию /assets/elements/chunks/ — так может его теперь тоже core/elements/ сделать — место очень удобное выбрано близко от корня и закрыто как и ядро, да и при написании сниппетов не придётся постоянно параметр tplPath указывать.
    Василий Наумкин
    31 мая 2016, 07:38
    0
    Так и сделано, просто не указывай больше &tplPath.
      Sem
      Sem
      31 мая 2016, 07:42
      0
      Круто! Василий, спасибо большое за твой труд. Теперь реально можно слезать с modxSmarty — Fenom рулит!!!
Sem
Sem
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.
      Sem
      Sem
      02 июня 2016, 07:22
      0
      Работает))
        Василий Наумкин
        02 июня 2016, 07:31
        +2
        Может, юзер должен быть авторизован в контексте, чтобы применялись его настройки, как думаешь?
          Sem
          Sem
          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