Идеальный шаблонизатор

Статус
В этой теме нельзя размещать новые ответы.

С.

Продвинутый новичок
Идеальный шаблонизатор

В стотысячный раз мы становимся свидетелями написания шаблона "с обратного конца". Есть у человека идея синтаксиса или реализации и дай, думает он, сделаем из этого шаблонизатор. Строить проект, отталкиваясь от его реализации -- немного странно, не кажется ли вам? Ничуть не менее странный и другой подход: "Чтоб как в Смарти, но быстрее".

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

Для начала определимся на берегу, что идеальный шаблонизатор это элемент "View" парадигмы MVC. То есть ничего, не относящегося ко View там не должно быть. Например кеширование результата работы шаблонизатора (выходных данных) не явлается его прерогативой. К этому не относится компилирование шаблона и кеширование кода. Эта часть, если она имеет место, является внутренней функцией шаблонизатора.

Базовая функциональность шаблонизатора:

- подстановка переменных
- условное ветвление
- организация циклов
- включение другого шаблона
- вызов функциональных модулей (для активных шаблонов)

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

Таким образом мы получаем следующий вывод: базовой функциональности шаблонизатора недостаточно для реальной работы. Практичный шаблонизатор должен обладать некоторой расширенной функциональностю.

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

Далее я предлагаю выработать подход к расширению фукциональности шаблонизатора без потерь его качеств, удобства использования и не внося неоправданных ограничений.

В чем собственно состоит смысл расширения функциональности? Мы привыкли говорить об отделении кода от представления (Model от View). Но оказалось, что кроме функционального кода, существует еще код представления. То есть мы обсчитали модель, выдали "на гора" результат и пихнули их во View. Но этого оказывается мало. Для построения соответствующего визуального представления во View надо написать немалый код.

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

Не спешите говорить, что это все просто. Мы ведь создаем идеальный шаблонизатор, а в идеальном шаблонизаторе дизайнер должен также иметь доступ к HTML, как и в базовой функциональности. То есть шаблон вида
Код:
  ...
  {MySuperMacros($data)}
  ...
не годится. Все HTML нутро этого макроса должно быть здесь же и совершенно очевидно и логично занимать свое место в общем потоке HTML.

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

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

Код:
  ...
  {TREE}
    <ul>
     {BRANCH}
       <li>{DATA}</li>
     {/BRANCH} 
    </ul> 
  {/TREE}
  ...
Вторая задача немного из другой степи. В принципе она решается базовой функциональностью, но де факто имеет очень "неопрятный" вид. Я говорю о создании форм. Из рассмотрения исключаются генераторы форм, вид которых задается где-то в другом месте, кроме шаблона. По сути задача состоит в создании генератора форм, встроенного в шаблонизатор. Условия те же: HTML код, отвечаюший за визуальное представление находится в шаблоне в "свободном доступе" и "на своем месте". Технические детали, как то присвоение начальных данных, возведение CHECKED или SELECTED должны быть скрыты.

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

pachanga

Новичок
Давай начнем с того, как ты думаешь PHP сам по себе уже шаблонизатор?
 

С.

Продвинутый новичок
как ты думаешь PHP сам по себе уже шаблонизатор?
PHP - шаблонизатор с базовыми функцями. Как "практичный" шаблонизатор он не годится и требует расширений.
 

pachanga

Новичок
Автор оригинала: С.
PHP - шаблонизатор с базовыми функцями. Как "практичный" шаблонизатор он не годится и требует расширений.
a) на счет того, что он не "годится" тут с тобой многие поспорят, b) если твой начальный пост был камнем в огород MACRO, то он как раз расширяет PHP, а не замещает его
 

Фанат

oncle terrible
Команда форума
pachanga
не стоит воспринимать все так лично. Пост этот - "камень в огород" и макры, и смарти, и хслт.
 

pachanga

Новичок
*****

Да все нормально, это ж оффтоп ;) Просто по-моему ты пока единственный, кто понял как работает MACRO.
 

С.

Продвинутый новичок
на счет того, что он не "годится" тут с тобой многие поспорят
Я предложил две контрольные задачи. Увы, решение их "в лоб" на PHP чрезвычайно уродливо.
 

Фанат

oncle terrible
Команда форума
По поводу идеальности шаблонизаторов.

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

Пых стал суперпопулярен благодаря своей простоте.
Хслт вызывает отвращение тем, что этот, по сути, язык программирования, реализован в чудовищном синтаксисе, "чтобы было похоже на XML".

С другой стороны, хслт реализует ту самую парадигму.
Ведь хочется из бизнес-логики получить массив с новостями, а уже в шаблоне делать по желанию: хочешь - выводи заголовки. Хочешь - текст в title к заголовку, а хочешь - обрезай по 1000 символов и выводи анонсами.

И здесь мы сталкиваемся с одной неприятной коллизией. Шаблонизатор в парадигме мвц - это инструмент ПРОГРАММИСТА.
Работать же с шаблоном часто приходится, как это ни печально - конечному ПОЛЬЗОВАТЕЛЮ.

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

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

jonjonson

Охренеть
Для начала определимся на берегу, что идеальный шаблонизатор это элемент "View" парадигмы MVC.
Совершенно не согласен. Я бы в соответствие View поставил элемент Response или httpResponse (как пожелаете). А шаблонизатор - это его обслуживающая часть. Кроме того шаблонизатор може использоватся и в других целях, например, формирование тела письма.

Response - это куда больше, как то возврат заголовков (ошибки, кэширование, отдача бинарных данных и т.д.), возврат данных в виде нужном данному клиенту (браузер, мобильный браузер, аякс приложение, клиент сервиса). Response должен существовать с начала и в любой момент вернуть нечто соответствующее ситуации. Хотя бы ту же ошибку.

От сюда я вижу все беды с шаблонизаторами. Ими пытаются подменить View, а это не правильно.
 

pachanga

Новичок
Я, в принципе, полностью согласен с *****ом. Практика использования различных шаблонизаторов показала - презентационной логики в шаблоне ну никак не избежать и с этим сам PHP справляется замечательно.

На счет "контрольных задач"...

Вывод дерева: в принципе, в MACRO можно сделать подобные макросы(кстати, спасибо за идею), например для такого входного массива:

Код:
$tree = 
array(array('title' => '...'), 
       array('title' => '...', 'kids' => 
                               array(array('title' => '...'), array('title' => '...'))));
Код:
{{tree using="$tree" kids_property="kids"}}
<ul>
{{tree:branch}}<li>
{{tree:item}}{$title}{{/tree:item}}
{{/tree:branch}}</li>
</ul>
{{/tree}}
Генератор форм: ты серьезно считаешь что это должно быть в шаблонизаторе? Мы подходим к этому иначе: генераторы(как и прочие визарды) - зло. "Шаг влево, вправо" и генератор не справляется.
 

Dagdamor

Новичок
По-моему, то же самое можно сделать рекурсивным вызовом шаблоном самого себя и не городить огород :)
Если исходные данные для вывода дерева - рекурсия, то проблем нет, с этим справится любой шаблонизатор и будет выглядеть просто и красиво. Если исходные данные - выборка из NS например, вот тогда сложнее.
 

С.

Продвинутый новичок
Генератор форм: ты серьезно считаешь что это должно быть в шаблонизаторе?
Отвлекись от слова "генератор". Напиши "красивый" шаблон с формой.
 

Духовность™

Продвинутый новичок
Как "практичный" шаблонизатор он не годится и требует расширений.
Можно тут поподробнее? Что подразумевается под расширением? Набор специфичных функция? почему это нельзя реализовать с помощью самого PHP?
 

С.

Продвинутый новичок
Мое имхо заключается в том, что основное свойство языка шаблонизатора - простота, удобство и понятность.
И я за это! Вот и прошу показать простой, удобный и понятный шаблон. Сначала концептуально, а потом в реализации.
 

pachanga

Новичок
Автор оригинала: С.
Отвлекись от слова "генератор". Напиши "красивый" шаблон с формой.
Как на счет такого:

Код:
{{form id="my_form" action="/some/action"}}

{{input name="title" class="input"/}}

{{textarea name="message" class="input"}}{{/textarea}}

<input type="submit">Go</input>

{{/form}}
Несколько замечаний по коду.

1) {{form}}, {{input}}, {{textarea}} практически полностью аналогичны своим HTML эквивалентам в том плане, что прининимают любые аттрибуты и отображают их as-is. Но кроме этого, они также связаны с компонентом формы, из которого черпают данные для заполнения значений. Эти макросы генерят PHP код, примерно подобный тому, на что похожи Rails, Symfony form helpers. Для полноты примера можно показать, как происходит связь с контроллером, однако...позже, если будет интерес.

2) Никто не мешает использовать обычную html разметку для простых вещей, где не требуется связь с моделью, например, submit кнопка Go так и сделана.
 

С.

Продвинутый новичок
Можно тут поподробнее? Что подразумевается под расширением? Набор специфичных функция? почему это нельзя реализовать с помощью самого PHP?
См. контрольные задачи. Когда реализуешь их и тебя не будет тошнить от вида такого "шаблона" или это вообще можно будет называть шаблоном, значит годится.

Как расширять? Как угодно! Лишь бы мы видели шаблон, а не макароны по-флотски. Вот pachanga привел одно из решений:

Код:
{{tree using="$tree" kids_property="kids"}}
<ul>
{{tree:branch}}<li>
{{tree:item}}{$title}{{/tree:item}}
{{/tree:branch}}</li>
</ul>
{{/tree}}
Нормальный шаблон. С небольшим излишеством в виде {{tree:item}}, но шаблон в полном смысле.
 

Dagdamor

Новичок
pachanga
Полагаю, речь о том, чтобы написать такую формочку безо всяких надстроек, на чистом PHP...
 

С.

Продвинутый новичок
Код:
{{form id="my_form" action="/some/action"}}

{{input name="title" class="input"/}}

{{textarea name="message" class="input"}}{{/textarea}}

<input type="submit">Go</input>

{{/form}}
А вот здесь ты дал маху. HTML в шаблоне должен оставаться HTML, а не становится еще одним phpBB-подобным уродцем.
 

Bakti9rov

!*|=?
По поводу скорости: имхо, идеальный шаблонизатор должен быть написан на С :D, поставляться в виде rpm и msi, легко ставиться на хостинге и висеть демоном на каком нибудь порте, в режиме сессий. Передача данных от пхп -- в виде YAML либо XML. Входные шаблоны -- tpl-файлы. Возвращаемый результат - готовый HTML.

В таком случае шаблонизатор будет "летать" вне зависимости от синтаксиса ! :)

Ну а по поводу синтаксиса -- имхо, в шаблоне должно присутствовать три обязательных момента:
а) шаблонные сущности
б) шаблонная разметка (блоки, "теги") и
в) шаблонные правила, которые в зависимости от разметки преобразуют шаблон.

Аналоги в (x)HTML:
сущности xHTML - это &amp;nbsp; &amp;amp; etc
разметка xHTML - это теги // <tag></tag>, <tag />, <tag>
правила xHTML - это стили CSS относительно тегов: tag{property:value;}

сущности XML - это &amp;nbsp; &amp;amp; etc
разметка XML - это валидные теги XML
правила XML - это XML-документ с тегами неймспейса XSL для XSLT-преобразований.

Так же и с шаблонизатором - должны быть сущности (переменные), должна быть разметка (блоки) и набор правил для шаблонной разметки.

сущности шаблона: {$var}
разметка шаблона: {block}{/block}
правила шаблона: это либо конфигурация, либо просто пхп-код (модули), либо какие то inline-инструкции к блоку.

По поводу правил шаблона, есть собственные наработки в этом направлении, кому нада пишите в ЛС. =))
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху