Доброго здравия хабражителям!

Когда я заглянул в исходники MODx Evolution, меня едва ли не хватил удар. Рефакторить, рефакторить и рефакторить, как, наверное, сказал бы Ильич. По сему меня хватило едва ли на пару недель рефакторинга, после чего я забросил это дело, ибо времени откровенно не было. Но разговор пойдёт не об этом.

Система шаблонизации MODx на мой взгляд — одна из самых лучших. Особенно хорошо постарались разработчики в MODx Revolution. Всё логично, расширяемо, гибко и прям-таки пасторально. Можно сказать, синтаксис шаблонизации MODx — это почти что отдельный язык разметки. Именно такое вот восхищение стало причиной, по которой я стал использовать эту методику в других проектах. И для того, чтобы не заколачивать микроскопом гвозди, то есть не ставить для лендингов MODx, но иметь возможность использовать эту шаблонизацию, я написал отдельный класс шаблонизатора. И даже дал название — QuadBraces.

Однако, первое, о чём хочу предупредить — это то, что привычные MODx-ерам чанки, шаблоны, сниппеты и расширения в парсере хранятся не в БД, а в файлах. Путь к файлу с данными шаблона определяется путём определения константы QBPARSER_TPL_PATH.

Возможности


  • Рекурсивная обработка текстовых данных;
  • Используемые типы элементов: чанки, константы, установки, плейсхолдеры, отладка, сниппеты, языковые конструкции, автоитераторы;
  • Возможность определения т.н. темплейт-паков (в папке шаблонов парсера), что позволяет разрабатывать, устанавливать и использовать готовые пакеты шаблонов (как в Неназываемом-Мною-Обычно-Движке);
  • Возможность структурирования шаблонного контента. Точка в алиасе чанка / шаблона / сниппета означает фактически разделитель директории;
  • Ошибки генерируют исключения, что позволяет легче отлаживать код;
  • Установка массива плейсхолдеров и «настроек» подразумевает дополнение существующих данных;
  • Готовые алгоритмы аксессоров;
  • В отличие от MODx глубина вложенности сниппетов ограничена только максимальным уровнем обработки парсера.


В сущности данный класс представляет собой рекурсивный обработчик текста на регулярках. Данные для плейсхолдеров и «настроек» определяются конечным разработчиком. Точно также и со сниппетами — это всё уже на совести того, кто будет использовать этот класс. В смысле сами пишите =)

Исходник класса доступен на GitHub здеся — github.com/XanderBass/quadbraces

Пример использования парсера:

<?php
  require 'qbparser.php';
  
  $parser = new QuadBracesParser();
  $parser->templatePack = 'default'; // Устанавливаем шаблон-пак
  $parser->template = 'index'; // Устанавливаем сам шаблон
  $parser->data = array(
    'foo' => 'bar',
    'pagetitle' => 'Тестовая страница',
    'content' => 'Hello world!'
  );
  $parser->settings = array(
    'my_setting' => 'Моя настройка аднака'
  );
  echo $parser;
?>


Обращаю внимание, что парсер поддерживает языковые конструкции. Словари должны содержаться в языковой папке (по умолчанию QBPARSER_TPL_PATH.'lang'.DIRECTORY_SEPARATOR), где каждая подпапка соответствует по своему имени языковой сигнатуре (например, en или ru). Каждый файл словаря должен иметь расширение lng и содержать набор строк, разделённых символом "|". Первый элемент такой строки является ключом, второй — элементом caption, третий — элементом hint.

При поиске чанков, шаблонов и сниппетов (и расширений) производится поиск т.н. локализованных элементов. Эта возможность позволяет создавать отдельные реализации чанков для определённых языков.

Кстати, к вопросу о переменных. Фактически добавить переменную равно добавлению плейсхолдера.
<?php
  $parser->data = array(
    'items' => array(
      array('id' => 1,'title' => 'Элемент 1'),
      array('id' => 3,'title' => 'Элемент 3'),
      array('id' => 2,'title' => 'Элемент 2')
    )
  );
?>

Этот код не приведёт к перезаписи всего массива data парсера. Этот код перезапишет лишь элемент «items» этого массива, если тот существует (если нет, создаст).

Поддерживаемые раширения


is, eq — равенство (сравниваемое значение, then, else)
isnot, neq — неравенство (сравниваемое значение, then, else)
lt — меньше, чем (сравниваемое значение, then, else)
lte — меньше, чем, или равно (сравниваемое значение, then, else)
gt — больше, чем (сравниваемое значение, then, else)
gte — больше, чем или равно (сравниваемое значение, then, else)
even — признак чётности (сравниваемое значение, then, else)
odd — признак нечётности (сравниваемое значение, then, else)
for — целочисленный итератор (количество итераций, start, splitter)
foreach — индексный итератор (список индексов через запятую, splitter)

— Для расширения for доступен внутренний плейсхолдер [+iterator+], содержащий
номер текущей итерации
— Для расширения foreach доступны внутренние плейсхолдеры:
[+iterator.index+] — номер позиции текущей итерации
[+iterator+] — текущий индекс

Примеры возможностей



{{path.to.my-chunk}}
выведет обработанное содержимое чанка, находящегося в файле /path/to/my-chunk.html в папке парсера. Как я уже говорил, возможность позволяет структурировать данные шаблонов, не сваливая всё в одну кучу.

{{my-chunk &foo=`bar`}}
выведет обработанное содержимое чанка my-chunk, заменив внутри него плейсхолдер [+foo+] на строку «bar». Эта фича позволяет обходиться без громоздких сниппетов-итераторов. Надо вывести в лендинге десяток проектов? Нет ничего проще! Создаём чанк вывода проекта, а на странице тупо несколько раз его вызываем, подставляя нужные локальные параметры — PROFIT!

[*cool-data &foo=`bar`*]
то же, что и выше, только с плейсхолдером cool-data.

[*cool-data:empty=`bar`*]
если плейсхолдер cool-data будет пустым, выведется строка «bar»

{*MY_CONSTANT*}
выведет содержимое константы MY_CONSTANT, если таковая определена. Работает с любыми константами. Аккуратнее с «волшебными» константами. Иногда случаются любопытные вещи.

[!my.cool.snippet:empty=`пустонафик` &argument=`foobar`!]
Выполнит сниппет my/cool/snippet.php из папки шаблона, передав в качестве аргументов массив, содержащий элемент с индексом argument и значением «foobar». Если результат работы сниппет будет пустым, выведет строку «пустонафик».

{{my_chunk:for=`6`:splitter=`< br / >`}}
выведет чанк my_chunk 6 раз, разделив при этом вывод при помощи тега < br / > (убрать пробелы в теге)

[%error-message.hint%]
выведет HINT языкового элемента error-string, если язык загружен

В общем бесконечно можно фантазировать о применении этого парсера. Базовые примеры есть в README на GitHub. По сему экспериментируйте. В комментариях задавайте вопросы, а также пишите об ошибках, если таковые будут. Я проверял — всё работает.

UPD 1:
— Теперь доступно на GitHub здеся — github.com/XanderBass/quadbraces
— По многочисленным заявкам (здесь была ирония) добавлены итераторы
— Код отформатирован немного лучше
— Добавлены языковые конструкции и поиск локализованных версий файловых элементов

UPD 2:
— Добавлены автоитераторы элементов массива data, являющихся массивами
А Вы делаете лендинги на MODx

Проголосовало 122 человека. Воздержалось 44 человека.

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

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


  1. IncorrecTSW
    14.09.2015 22:37
    +2

    Я просто оставлю это здесь.


    1. IncorrecTSW
      14.09.2015 22:46
      +1

      Кроме того для таких простыней лучше подойдет реп на гите или гист.


  1. SerafimArts
    15.09.2015 00:37
    +4

    > Когда я заглянул в исходники MODx Evolution, меня едва ли не хватил удар. Рефакторить, рефакторить и рефакторить, как, наверное, сказал бы Ильич.

    Открыв спойлер, у меня примерно такое же желание появилось… :) Для начала PSR, что по ссылке выше от IncorrecTSW, а далее по-Макконнеллу: Разнести на классы, разделить километровые методы на несколько более мелких и так далее. Плюс composer.json и прочие «ништячки».


    1. XanderBass
      15.09.2015 09:42
      -1

      Зачем плодить лишние сущности, когда всё упирается по сути в один единственный алгоритм? Его можно было бы сделать обычной рекурсивной функцией. Но во-первых, тут, конечно, была бы действительно километровая функция. А во-вторых, настраиваемости не было бы никакой.


      1. GrizliK1988
        15.09.2015 09:57
        +1

        Зачем плодить лишние сущности, когда всё упирается по сути в один единственный алгоритм?


        Вот думаю та причина, по которой вам так хотелось сделать рефакторинг modx.


  1. nitso
    15.09.2015 01:37
    +3

    Когда-то давно-давно это было бомбой.
    Чем ваше решение лучше, например, твига?


    1. Fesor
      15.09.2015 03:10
      +1

      Давайте так, есть что-то лучше twig-а?


      1. nitso
        15.09.2015 03:26

        Все зависит от решаемых задач. Например, есть реализация mustache или Fenom, о котором писали на хабре.

        Мое личное мнение: по-быстрому и по-простому отлично работают обычные php-шаблоны с минимальной обвязкой. В остальных случаях предпочитаю twig.


        1. Fesor
          15.09.2015 11:20
          +1

          Чем мне нравится twig — так это архитектурой, вы можете сделать из него что угодно. У вас есть возможность добавлять свои парсеры, обрабатывать AST шаблонов и т.д. Скажем можно красиво добавить поддержку jade в шаблоны твига или сделать то же что и у мусташ, но на базе twig-а.

          В целом мне без разницы, у меня всеравно на сервере только api, а рендринг вынесен целиком и полностью на клиент.


    1. XanderBass
      15.09.2015 10:06
      +2

      Во-первых, проще. Зная систему шаблонизации MODx/Etomite, не придётся ломать голову над документацией. Во-вторых, оное не кушает несколько мегабайт во время работы, что позволяет использовать это решение на любом хостинге, даже на самом говённом. А исходник занимает 13 с копейками килобайт в одном файле.

      Да, я помню одно из правил хорошего тона современного разработчика: везде и всегда использовать современные решения. А я вот недавно самостоятельно провёл бенчмарк PDO и mysqli. В результате теперь я не просто обхожу PDO стороной, а очень далёкими околицами, ибо эта срань жрёт ОЗУ раз эдак в шесть больше, чем mysqli, и раз в десять (!) больше, чем нативный php-mysql. А выигрыша по времени всё равно нету. К тому же я привык вместо использования всяких ORM-ов просто нормально писать запросы. Так что все эти рюшечки современных средств лично мне ни к чему. Ровно то же самое можно сказать и о любом другом сравнении современного модного трендового продукта и легковесного решения.


      1. IncorrecTSW
        15.09.2015 10:28
        +2

        С таким подходом вам дальше лендингов будет трудно уйти.


        1. XanderBass
          15.09.2015 10:57

          Ну вот здесь я поспорю. Мой подход просто весьма консервативен. Но он не означает, что я не стану использовать какие-либо решения, кушающие больше ресурсов, чем нативный HTML/CSS/PHP/MySQL. Каждой задаче — своё решение. Другой вопрос, что, скажем, использовать в высоконагруженном проекте PDO я бы не стал, а вот mysqli — без проблем. Вот, собственно, и вся суть подхода.

          В разрабатываемой мною CMS в качестве шаблонизации используется как раз QuadBraces. В качестве расширения для работы с БД — php-mysqli. Результат — очень гибкая и многофункциональная CMS со средним временем отработки 15-20 миллисекунд и расходом ОЗУ не более 1,5 мегабайт (с дополнительными модулями). По экономии ресурсов «делает» даже мой любимый MODx Evolution (про Revo с его xPDO промолчу, ладушки). На такой CMS можно делать, мягко говоря, далеко не только лендинги.

          Чем больше я смотрю на современные средства разработки, тем больше убеждаюсь, что оные — для ленивых. А самый удивительный парадокс заключается в том, что в сущности разницы по времени разработки никакой. А вот ресурсоёмкость в случае с консервативным подходом значительно меньше. В принципе оно объяснимо, ведь сейчас компьютеры большие и мощные. Вот только шансов, что упадёт, у «консервативной» системы куда меньше, чем у «трендовой».


          1. Fesor
            15.09.2015 11:33
            +1

            использовать в высоконагруженном проекте PDO я бы не стал, а вот mysqli — без проблем

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

            Я вообще не понимаю почему вы пишите на php при таком подходе, писали бы на python, где есть fastcgi настоящий или вообще на java, где нет расходов на бутстрапинг приложения ит.д. Ну или хотя бы reactphp, при наличии mysqli и его асинхронных запросов а так же корутин профит будет гораздо больше. Скажем у меня есть pet-project на Symfony2+Doctrine2, пожалуй одна из самых прожорливых комбинаций. Так вот, вместе с php-pm у меня в среднем время ответа выходит 50ms. И это на php5.6, на php7 все станет еще лучше. Подобные извращения полезны когда для нас уменьшение времени обработки запроса на 10ms это существенно. Но таких проектов меньше 0.1% от общей массы.

            Чем больше я смотрю на современные средства разработки, тем больше убеждаюсь, что оные — для ленивых.

            Не для ленивых, а для тех кто ценит свое время и деньги клиента.

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

            Да, по времени разработки разница будет минимальна. А вот поддерживать эту систему выйдет сильно дороже, рефакторить такую систему будет дороже, добавлять функционал — дороже. А если у нас еще будет сложная бизнес логика мы можем просто заплакать. В принципе можно вкатит CQRS и под копотом делать любую сатану которую вы пожелаете, и тогда будет вроде бы и норм, но что-то мне подсказывает что это не для вас.

            ну и да, если мы говорим о системах для генерации лэндингов и т.д проще просто поставить сверху варниш какой.


            1. PerlPower
              16.09.2015 00:40
              +4

              Ну чего вы докопались до человека? У него другие реалии разработки, и ему удобны другие инструменты. Он делает проекты и получает за них деньги, скорее всего меньше чем вы, но не потому, что делает плохо, а потому что вы работаете на людей с разными кошельками.

              Да, по времени разработки разница будет минимальна. А вот поддерживать эту систему выйдет сильно дороже, рефакторить такую систему будет дороже, добавлять функционал — дороже. А если у нас еще будет сложная бизнес логика мы можем просто заплакать. В принципе можно вкатит CQRS и под копотом делать любую сатану которую вы пожелаете, и тогда будет вроде бы и норм, но что-то мне подсказывает что это не для вас.


              Но автор же ясно выразился, что занимается лэндингами и интернет-магазинами(а там скорее всего движок уже готовый), и что его основное окружение — шаред хостинг.

              И ведь забавно, что такие как автор вполне могут уделать по эффективности вас. Ну просто он напишет быстрее. А рефакторить потом по сути и нечего, функционал добавляться тоже будет мало — проекты такого рода небольшие обычно. Почему бы просто не признать как данность, что есть класс задач, которые максимально эффективно решаются именного говнокодом и велосипедами заточенными под себя?


              1. XanderBass
                16.09.2015 10:36

                Вот! Золотые слова! Жаль, что плюсануть не могу. Правда, всё-таки отмечу, что говнокодом задачи не решаются. Говнокодом обычно фиксятся баги. Собственно, это и есть основной механизм размножения говнокода в проектах. Посеял маленькое говнецо — а оно потом обрастает костылями.


                1. Fesor
                  16.09.2015 10:41

                  Everybody poops, but usually doing it in one place.

                  Я сторонник идеи что говнокоду есть место в проекте, где-нибудь за красивым интерфейсом.


      1. nitso
        15.09.2015 18:04

        Да, вселенная оптимизации сайта под дешевые хостинги и бережливых клиентов существует где-то рядом. Быстро забывается и отсутствие ssh, и пляски с загрузками мегабайтных архивов с кодом через панель управления, поскольку ftp сутками прокачивает тонну мелких файлов.

        Это очень, не побоюсь этого слова, нишевая разработка с другими подходами.


        1. XanderBass
          15.09.2015 19:20
          +1

          Ну, что ж, можно ждать тыщу лет клиента с хорошим проектом. Если, конечно, есть на что кушать и оплачивать квартиру. А можно не брезговать и «нишевыми» заказами (на минуточку не менее 80% владельцев сайтов рунета) и иметь хотя бы маленький доход от оных. Даже в «кризис». Не знаю, как Вы, а я свой выбор сделал ;)

          Под дешёвыми хостингами в данном случае понимается всё под определением «виртуальный хостинг».


          1. Fesor
            15.09.2015 20:11

            ну да, если ждать. А можно не ждать а искать самому. Вы удивитесь, но клиентов с такими вот «нишевыми» вещами становится все меньше и меньше а проектов в рунете интересных прибавляется, даже в период кризиса. Позитивные тенденции вроде psr-стандартов, composer и т.д. уже потихоньку переходят и в эту нишу, хостинги все больше и большей ориентируются на клиента, а оттуда и ssh и прочие плюшки вроде последних версий пыха или возможность использовать nodejs и т.д… Да и VDS за 5 баксов не сложно нынче купить, и многие уходят в эту сторону, так как экономия двух баксов и кастыли которые из-за этой экономии приходится впиливать — это так себе экономия.


            1. nitso
              15.09.2015 21:15

              Любая работа может быть интересной, это вопрос личного восприятия. Я сейчас с приятной ностальгией вспоминаю то, о чем говорит XanderBass.
              А что касается VDS за 5 баксов — большинство по качеству (производительности) не далеко ушли от шареда, просто повышают ЧСВ за счет роста ответственности. И приходится так же заниматься оптимизацией, придумывать способы избавиться от лишнего балласта, писать свои узкоспециализированные решения вместо использования популярных библиотек-комбайнов.

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


              1. Fesor
                15.09.2015 21:52

                просто повышают ЧСВ за счет роста ответственности

                а еще позволяют делать всякие разности вроде continuous deployment. Про то что качеством они далеко не ушли это я согласен полностью.


  1. XanderBass
    15.09.2015 13:24

    > Вы же понимаете что сейчас проще докупить пару серверов
    > чем оплачивать работу программиста что бы тот оптимизировал все до потери сознания?

    Для заказчика проще. А мне вот, как разработчику, совесть не позволит делать прожорливые, толстые проекты, по функциональности не соответствующие своей прожорливости. Это во-первых. Во-вторых, Вы, видимо, не сталкивались в своей практике с заказчиками, которые вообще ничего, кроме виртуальных хостингов не признают. А есть (о, ужас!!!) такие, которые признают только дешёвые хостинги. А проектов на виртуальных хостингах — открою Вам глаза — более 80% от общей массы по меньшей мере в рунете. Менее 20% владельцев сайтов в сети имеют свои выделенные серверы. Потому что держать ради одного среднестатистического интернет-магазина сервер и штат программистов, мягко говоря, накладно. А среднестатистическому проекту, если оный грамотно разработан, вполне хватит в месяц часа CPU и стандартных 64-128 Мб ОЗУ. Это уже из личного опыта поддержки трёх интернет-магазинов.

    > А вот поддерживать эту систему выйдет сильно дороже,
    > рефакторить такую систему будет дороже, добавлять функционал — дороже.

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

    — Настоящий художник может нарисовать шедевр даже гвоздём на стекле. Всё зависит от уровня мастерства.

    А то, что изначально написано грамотно, оптимизировать вряд ли потребуется.


    1. Fesor
      15.09.2015 14:29
      +1

      А то, что изначально написано грамотно, оптимизировать вряд ли потребуется.

      premature optimization короче, я вас понял. А вы нагрузочные тесты может еще пишите когда выдумываете такие подходы? Что-то сомневаюсь.

      Вы, видимо, не сталкивались в своей практике с заказчиками, которые вообще ничего, кроме виртуальных хостингов не признают.

      Я не работаю с такими клиентами, и обычно я навязываю что должен использовать клиент, ибо как правило он не шарит. Да и клиенту это выгодно, ибо в случае когда я контролирую куда кто будет деплоиться, я могу воспользоваться штуками типа ansible и сократить издержки на рутину, вроде деплоймента.

      А проектов на виртуальных хостингах — открою Вам глаза — более 80% от общей массы по меньшей мере в рунете.

      Как бы так сказать, меня не интересуют эти 80%. Вот совсем не интересуют.

      — Настоящий художник может нарисовать шедевр даже гвоздём на стекле. Всё зависит от уровня мастерства.

      Вот только пользователю вашей системы или даже клиенту глубоко плевать что там внутри, шедевр или кусок гуано. Им главное что бы это работало, приносило деньги и позволяло развиваться дальше. Возможно по этому бэкэндеры так много пьют.

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


      1. XanderBass
        15.09.2015 16:51
        -1

        > premature optimization короче, я вас понял. А вы нагрузочные тесты может еще пишите
        > когда выдумываете такие подходы? Что-то сомневаюсь.

        Сомневайтесь, Ваше право. Вот только я всегда всё тестирую — каждую мелочь. И, да, premature optimization и просто грамотная разработка — это разные вещи. Если я изначально использую грамотный алгоритм, отшлифованный до мелочей — это второе, а не первое. И в случае с изначально грамотным проектированием оптимизировать обычно ничего не требуется. Минимум кода, максимум эффективности.

        > Я не работаю с такими клиентами, и обычно я навязываю что должен использовать клиент,
        > ибо как правило он не шарит.

        Вот на этом месте, собственно, можно завершить нашу беседу, ибо у нас совершенно разный подход к клиенту. У меня подход ориентирован на самого клиента, а не на моё `авторитетное` мнение. Если клиент беден, как церковная мышь, я всё равно беру заказ и делаю его на совесть, даже если мне потребуется раскурить для этого десятки мануалов. У Вас же всё опирается на Вашу точку зрения, как лучше. В этом, собственно, вся соль нашей дискуссии.


  1. NeX
    15.09.2015 23:48
    +3

    Скажите пожалуйста, чем вот это

    [!my.cool.snippet:empty=`пустонафик` &argument=`foobar`!]
    

    проще и понятнее, чем
    {% if !my_cool_snippet(argument='foobar') %}
       пустонафик
    {% endif %} 
    


    И еще расскажите, как на этом чудо-шаблонизаторе сделать, например, простой цикл for


    1. bezumkin
      16.09.2015 08:20

      А никак. И переменную не присвоить и еще много чего не сделать. Это, по сути, такой продвинутый str_replace(placeholders, values) и ничего больше.

      Именно поэтому я интегрировал в MODX Revolution нормальный шаблонизатор Fenom, а тут, выходит, обратный процесс.


      1. sashabeep
        16.09.2015 10:27

        Я вот периодически послеживаю за вашими постами и наработками и думаю — зачем вам MODx? Вы его перелопатили так что дальше некуда


        1. bezumkin
          16.09.2015 10:59

          Странный, какой-то, у вас вопрос. MODX мне нравится — вот и работаю с ним.

          Пишу дополнения, которые расширяют его функционал и не меняют при этом ядро системы. Никаких «перелопачиваний» или хаков нет, везде используются штатные возможности системы.

          И да, советую еще вот эту заметку, а то неправильное написание названия режет глаз.


          1. sashabeep
            16.09.2015 11:58

            Я не имел в виду никакой критики, но с вашим стремлением вы бы давно запилили свой движок. И магазин дополнений к нему же.
            Спасибо за ссылку, раньше какая-то катавасия в названиях была, так что у evo/revo отличались буквы.


            1. bezumkin
              16.09.2015 12:04
              +1

              Я поработал с MODX достаточно, чтобы понять — такое я не запилю =)

              Серьёзно, создавать свою CMS, развивать и поддерживать — это же адский труд, зачем? И чем она будет лучше? Тем более, что меня в Revolution почти всё устраивает, а что нет — расширяю дополнениями или отправляю в ядро pull-requests. В итоге сформировалась приличная библиотека готовых актуальных решений, которые я могу использовать почти на любом проекте.

              А магазин дополнений, и даже свой хостинг для MODX, мы уже сделали, так что и здесь вопросов нет.


              1. sashabeep
                16.09.2015 13:10

                Да если поставить и использовать все ваши расширения, то от MODX останется чей только раздел настроек и немного ядра :) Про магазин в курсе


                1. bezumkin
                  16.09.2015 13:15

                  Да ладно вам.

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


    1. XanderBass
      16.09.2015 10:24

      Минуточку. Вот в моём случае выполнится код, заложенный в сниппете (а там может быть очень много кода). А что в результате выполнится у Вас? Ну да ладно, Вам виднее.

      Лично мне, как и любому человеку, не знакомому с Twig, но знакомому с MODx, будет проще и понятнее. Послушайте, никто не говорит, что это супер-бомба, призванная похоронить продвинутые трендовые шаблонизаторы. Эта штуковина создана только с одной целью (цитирую):

      для того, чтобы не заколачивать микроскопом гвозди, то есть не ставить для лендингов MODx, но иметь возможность использовать эту шаблонизацию

      Кстати, насчёт переменных, циклов и прочего. По моему глубокому убеждению логика сложнее if-then-else — это уже программирование. IMHO, программировать в шаблонизаторах — это примерно то же самое, что раскатывать асфальт велосипедом.


    1. XanderBass
      16.09.2015 14:22

      Теперь, например, так:

      {{item-chunk:for=`6`:splitter=`<br />`}}
      


      В самом чанке допустимо использовать внутренний плейсхолдер [+iterator+], поддерживающий в свою очередь расширения.


  1. sashabeep
    16.09.2015 10:30

    Modx люблю, постоянно с ним работаю, но не могу пока придумать, для чего мне понадобился бы такой «шаблонизатор» для лендингов


    1. XanderBass
      16.09.2015 10:55

      Да пожалуйста =)

      На лендинге нужно вывести портфолио из нескольких проектов. Периодически проекты добавляются или убираются. Вёрстка каждого элемента одна и та же. Ну, разве что меняется парочка классов. Брать только из-за портфолио MODx — всё то же заколачивание гвоздей экскаватором. А чистый HTML поддеживать — адский трудЪ. Поверьте, я не на словах знаю, о чём говорю, у меня есть парочка таких проектов на поддержке. Дык вот берём этот шаблонизатор и пишем чанк (назовём его item) с вёрсткой одного элемента, допустим так:

      <div class="item" id="item-[+item-id+]">
        <h2>[+item-title+]</h2>
        <img src="/images/[+item-id+]/1.jpg" />
        <p>[+item-description+]</p>
        <div class="galery-wrapper">
          <img src="/images/[+item-id+]/1.jpg" />
          <img src="/images/[+item-id+]/2.jpg" />
          <img src="/images/[+item-id+]/3.jpg" />
          <img src="/images/[+item-id+]/4.jpg" />
          <img src="/images/[+item-id+]/5.jpg" />
        </div>
      </div>
      


      Разумеется, на практике будет много сложнее, чем эти несколько строк. Далее, дабы потом не копаться, вынесем элементы портфолио в отдельный чанк (назовём его items), где тупо их списочком, списочком:

      {{item &item-id=`1` &item-title=`Крутой проект №1` &item-description=`Наш первый крутой проект`}}
      {{item &item-id=`2` &item-title=`Крутой проект №2` &item-description=`Наш второй крутой проект`}}
      {{item &item-id=`3` &item-title=`Крутой проект №3` &item-description=`Наш третий крутой проект`}}
      {{item &item-id=`4` &item-title=`Крутой проект №4` &item-description=`Наш четвёртый крутой проект`}}
      {{item &item-id=`5` &item-title=`Крутой проект №5` &item-description=`Наш пятый крутой проект`}}
      


      Соответственно, в сам лендинг мы тупо вставляем чанк {{items}}. Итого убили двух зайцев: не потребовалось ставить MODx и сделали легко поддерживаемую систему. Для того, чтобы добавить, отредактировать или убрать элемент, достаточно будет править содержимое чанка items.


      1. Fesor
        16.09.2015 12:21
        +2

        А что бы так:

        {% for work in portfolio %}
        <div class="item">
          <h2>{{work.title}}</h2>
          <img src="{{work.thumb.src}}" />
          <p>{{ work.description }}</p>
          <div class="galery-w
        rapper">
            {% for image in work.images %}
            <img src="{{image.src}}" alt="{{image.alt}}" />
            {% endfor %}
          </div>
        </div>    
        {% endfor %}
        


        Причем если хочется модульности можно все так же разбить на миксины/виджеты. Неужели вам нравится такой подход?


        1. XanderBass
          16.09.2015 18:02

          Следите за коммитами на гите. Я добавил функционал, позволяющий проходиться циклом по элементам массива data парсера, являющимися массивами. То есть теперь для вывода портфолио можно добавить в массив data парсера элемент с ключом, скажем, items и вывести портфолио вот так

          {!items &chunk=`item`!}
          


          Если каждый элемент массива, являясь в свою очередь массивом будет содержать, скажем, элементы с ключами id, title, desc, то итератор (в промежуточной стадии) выведет следующее:

          {{item &id=`id_элемента_1` &title=`title_элемента_1` &desc=`desc_элемента_1`}}
          {{item &id=`id_элемента_2` &title=`title_элемента_2` &desc=`desc_элемента_2`}}
          {{item &id=`id_элемента_3` &title=`title_элемента_3` &desc=`desc_элемента_3`}}
          {{item &id=`id_элемента_4` &title=`title_элемента_4` &desc=`desc_элемента_4`}}
          


          Замечу при этом, что парсер по прежнему кушает совсем немного =)

          И спасибо за идею ;)


      1. bezumkin
        16.09.2015 12:22

        Ну а в нормальном шаблонизаторе было бы что-то вроде:

        {foreach $items as $item}
            {include 'item.tpl' item=$item}
        {/foreach}
        

        и шаблон item.tpl:
        <div class="item" id="item-{$item.id}">
            <h2>{$item.title}</h2>
            <img src="/images{$item.id}/1.jpg" />
            <p>{$item.description}</p>
        
            {if $item.images}
            <div class="galery-wrapper">
                {foreach $item.images as $image}
                <img src="/images/{$item.id}/{$image.id}.jpg" />
                {/foreach}
            </div>
            {/if}
        </div>
        

        При этом можно использовать проверку на пустые или несуществующие переменные, фильтры, кэширование и еще много чего. Не удивлюсь, если в итоге шаблонизатор будет работать быстрее, чем свой, вроде бы более простой, парсер.

        Ваш способ, конечно, имеет право на жизнь, но лично мне использование синтаксиса MODX вне этой системы непонятно.

        Для примера — вот простейший мини-движок, написанный в обучающих целях, который подходит для разных там визиток и прочей простоты. В нём я постарался воплотить принципы работы MODX, но в более современной обёртке.


        1. Fesor
          16.09.2015 12:54

          Мне еще нравится вариант с макросами для большей гибкости.

          {# work.html.twig #}
          
          {% macro small_preview(work) %}
          <div class="portfolio-item portfolio-item--small">
            <h2>{{work.title}}</h2>
            <img src="{{work.thumb.src}}" />
            <p>{{ work.description }}</p>
            <div class="galery-w
          rapper">
              {% for image in work.images %}
              <img src="{{image.src}}" alt="{{image.alt}}" />
              {% endfor %}
            </div>
          </div> 
          {% endmarco %}
          


          {# portfolio.html.twig #}
          {% import 'work.html.twig' as work %}
          
          {% for item in portfolio %}
          {{ work.small_preview(item) }}
          {% endfor %}
          


          1. bezumkin
            16.09.2015 12:57
            +1

            Если что — я не вам писал о нормальном шаблонизаторе.

            Мы оба пишем автору топика об одном и том, только я на Fenom, а вы на Twig.


            1. Fesor
              16.09.2015 13:26
              +1

              Я заметил, поправил. Просто вариантов как это организовать столько, что вообще не понятно зачем людям свои велосипеды.


              1. bezumkin
                16.09.2015 13:28

                Как знатный велосипедостроитель могу ответственно заявить — это очень весело и познавательно.

                Только сообщество такое не ценит и с публикацией велосипедов на Хабре нужно быть очень осторожным.


                1. XanderBass
                  16.09.2015 14:05

                  У меня есть поговорка на этот случай:

                  — Если хочешь лучше понять принцип работы и устройство велосипеда, изобрети его сам.


      1. sashabeep
        16.09.2015 13:09

        Не вижу проблемы скормить JSON по урлу или обычный массив


        1. XanderBass
          16.09.2015 13:20

          Можно и обычный массив. Однако, если учесть, что в чанке items каждая строка — это элемент, можно создать простой скрипт, который будет редактировать чанк items. И таким образом совершенно без использования СУБД мы можем реализовать простейшую панель управления для заказчика. Если включить фантазию, можно извернуться и вообще сделать своеобразную NoSQL-CMS.


          1. Fesor
            16.09.2015 13:29

            Если включить фантазию, можно извернуться и вообще сделать своеобразную NoSQL-CMS.

            Был у меня такой проектик, где страницы составлялись из блоков по аналогии с sir-trevor, а блоки сами парсились из шаблонов. Вышло довольно удобно, особенно для маркетологов с их желанием иметь возможность редактировать все и вся и при этом без возможности поломать верстку. Вместо html — markdown урезанный и чуть допиленный под нужды маркетологов (a/b тестирование). Как по мне для лэндингов, портфолио и т.д. самое то, с учетом того что все это еще и собиралось в html.