Как стать автором
Обновить

Комментарии 39

почему-то каждый велосипедист пытается сделать из шаблона кастрированный язык программирования… зачем тебе срезы массивов? зачем в шаблоне вообще циклы? какая шаблону разница между массивом и хэш-таблицей?
Ну, циклы наверно все-таки нужны, как же без них?
не помню когда последний раз ими пользовался в xslt %-)
Не мудрено, что не помните, xslt декларативен, какие ещё там циклы?
Зачем нужные циклы? в blitz вот прямого цикла нет, но блок итерируеться ровно столько раз сколько элеметнов в массиве. в js разве нельзя использовать один блок N раз?

Пример токой


{{PP}}


подаем данные

$ar['BLOCK'][] = array(«PP»=>1);
$ar['BLOCK'][] = array(«PP»=>2);
$ar['BLOCK'][] = array(«PP»=>3);
$ar['BLOCK'][] = array(«PP»=>4);

на выходе
1234
Ну, циклы наверно все-таки нужны, как же без них?

На достаточно высоком уровне абстракции без явных циклов частенько можно обойтись. Вот возьмём к примеру SQL (да, не шаблонизатор, но идея вполне применима, IMHO): в большинстве случаев если хочется сделать цикл — это ошибка.
Это у вас шутки такие?
Как, по вашему, пройтись по элементам массива без цикла?
Поверьте, срезы массивов тоже бывают нужны. Количество элементов в массиве данных не всегда удается изменить здесь и сейчас. Источник данных один, в шаблоне используется в двух местах, но где-то первая половина, где-то вторая. Как-то вы агрессивно реагируете.
если ты не можешь менять поступающие в шаблон данные, то в шаблонизатор нужно встроить полноценный язык запросов к данным. что если нужно вывести не половину, а каждый второй или каждый с положительным значением параметра? существует бесчисленное множество вариантов фильтрации входящих данных.

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

Второй абзац не понял, но думается вы хотите что-то сказать, связанное с xslt. От того, что выборка определенных элементов производится по какому то признаку, и проход по ним для вас прозрачен, это не отменяет итерации этих элементов.
почему одно в шаблоне а другое в контроллере?

по секрету скажу, что никаких циклов тоже выполняться не будет — просто указатель на текущую машинную команду будет менять значения. но это прозрачно для вас.
Единственный весомый аргумент в пользу шаблонизатора — изоляция от приложения, но удручает, что его добиваются через создания нового языка программирования.
Боюсь, что ваша затея обречена на провал. Слишком разные языки могут использоватся на сервере: php, perl, ruby, python, java, c#, vb.net, и сделать хорошо всем не получится никогда.
Безусловно не будет просто. Но сами посудите, данные для всех одинаковы. Основные конструкции присутствуют в каждом языке программирования. Конечно совсем все языки программирования не получится, но это и не самоцель.
Один тег из реального проекта на Django:
<div class="plate-dishes-item {% if not dish.enabled %}plate-dishes-item_disabled{% endif %}" 
	data-order-id="{{ dish.order_id }}" 
	data-dishoptions="{{ dish.dishoption_count }}" 
	data-add-url="{% if dish.dishoption_count > 1 %}{% url buy-dish-options dish=dish.id %}{% else %}{% url buy-cart-add dishoption=dish.option_id %}{% endif %}"
	data-include-id="{{ dish.id }}"
	data-hide-on-sort="{% if dish.hide_on_sort %}1{% endif %}">

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

<div class="plate-dishes-item % if not dish.enabled %plate-dishes-item_disabled% endif %" 
	data-order-id="% dish.order_id %" 
	data-dishoptions="% dish.dishoption_count %" 
	data-add-url="% if dish.dishoption_count > 1 %% url buy-dish-options dish=dish.id %% else %% url buy-cart-add dishoption=dish.option_id %% endif %"
	data-include-id="% dish.id %"
	data-hide-on-sort="% if dish.hide_on_sort %1% endif %">

Помоему, вообще ад.
Да, уже понял что неправильно выразился. То, что конструкции шаблонизатора обрамлены процентами, это просто в качестве примера, чтобы отвлечь от разделителей своё внимание…
Наверное стоило их совсем убрать из примеров…
а хороший шаблон выглядит так:
[div class=«plate-dishes-item plate-dishes-item_disabled_{enabled}»
data-order-id="{order_id}"
data-dishoptions="{dishoption_count}"
data-add-url="{add_url}"
data-include-id="{id}"
data-hide-on-sort="{hide_on_sort}"
]
Хороший шаблон выглядит так:
<dish data="item" />
это не шаблон
То, что «внутри» не должно нас волновать только 1% времени работы
я не понимаю может быть чего-то, но:
  1. Да, здесь я согласен в общем-то.
  2. Немного не понимаю о чем идет размышление если почти во всех языках есть: if ([условие]) {[тело]} else {[тело]}, зачем изобретать что-то?
  3. Опять же почти во всех языках есть while, for и foreach
    tenshi, циклы довольно часто нужны, например выводить те же комментарии или список записей в блоге
  4. И снова почти во всех языках есть include [имя того что инклюдим] можно даже сделать неймспейсы.
  5. Наследование… может быть я чего-то не знаю, но ниразу не видел, что бы была необходимость наследовать шаблоны.

Если в чем-то не прав — поясните, очень уж интересно.
2. Как отметил в топике, в javascript нет оператора unless. Стоит ли его реализовать в шаблоне?
5. Статья на хабре про наследование в Django: habrahabr.ru/blogs/django/23132/

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

а наследование конечно всегда можно заменить лесенкой ифов, да. просто разные уровни абстракции
тогда как вы предлогаете выводить все те же комментарии?
{block:commentList}
comments:
[ul]
{block:apply}
[/ul]
{/block:commentList}

{block:commentList empty}
no comments
{/block:commentList}

{block:comment}
[li]
{author}: {message}
[/li]
{/block:comment}
немного не в курсе данного синтаксиса, но в сущности это разве не цикл?
тут 3 шаблона с плейсхолдерами. где ты тут разглядел цыклы?
Видимо не так понял данный синтаксис.

В таком случае не понимаю, что вообще происходит в этих шаблонах. Это смарти? =)
в принципе можно и к смарти такую штуку прикрутить. шаблонизатор под данные подбирает шаблон из имеющихся рекурсивно итерируя входные данные. вместо того, чтобы шаблон вытягивал данные, проходил по ним циклом, переименовывал текущий контекст и тп…
Мне кажется, что tenshi просто прикалывается, а народ ведется. Он думает о шаблоне с функциональными корнями: что бы отобразить (преобразовать) список не нужны циклы, нужен Map. Остальные смотрят на шаблон императивно и не рубят, как тут можно без циклов =)
unless — я считаю почти не нужным оператором ведь всегда можно сделать: if (!true) {}.

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

unless не нужен. Достаточно if, while и for i in list (опционально можно добавить for i in range(a, b) ).

Запись list.3 меня вводит в ступор, это некрасиво.

Я думаю, стоит проанализировать несколько распространенных языков и посмотреть, в каком виде там встречается вложенность объектов. В JS, например, всё единообразно, а в PHP бывают и ключи массива, и свойства/методы объектов, но тип объекта взаимоисключает эти два случая. В питоне не исключает — у объекта могут быть и свойства, и ключи массива.

п. 4 — совсем не понял, что у вас в примере написано, какое-то nameinclude. Про передачу переменных: мне нравится, как в Smarty — там при инклюде передается весь текущий контекст. Например, можно написать
{foreach from=$list item=i} {include file='file.html'} {/foreach}
и в file.html будет передана переменная $i.

Наследование — мне нравится, как в Django. Не вижу особых недостатков.
Запись list.3 меня вводит в ступор, это некрасиво.

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

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

4. Инклуды
<!-- Вставить в шаблон инклуд nameinclude  -->
% nameinclude %
<!-- Вставить в шаблон инклуд tpl_comments, передать в качестве текущего объекта, объект по адресу source.comment_data  -->
% tpl_comments => source.comment_data %

В первом случае мы вставляем инклуд nameinclude, в качестве текущего объекта, будет объект, в контексте которого идет вызов инклуда. Во втором случае текущим объектом в инклуде tpl_comments будет выступать объект source.comment_data
Имхо в примере с tpl_comments => source.comment_data стоит тогда стрелку в другую сторону делать.
Вполне себе вариант, как-то не задумывался, но приму к сведению. По смыслу как то больше подходит
Целесообразность в наследовании может отпасть с возможностью управления именем вставляемых инклудов.
хотелось бы на это посмотреть х)
Ммм, в чем ирония?
<!-- инклуд с именем, указанным в шаблоне -->
{& commentlist }
<!-- инклуд с именем, заданным в переменной -->
{& #name.inc.comment }

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

Так сложно такое представить? Не подходит для составления основного шаблона из разных кусочков?
сложно такое использовать. вместо того, чтобы просто нарисовать новый шаблон, нужно нарисовать новый шаблон и присвоить заданной переменной его имя. никто не будет это использовать без _крайней_ необходимости. к тому же, там косяки с очерёдностью присвоений. сначала внешний шаблон присваивает имя переменной, потом внутренний.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории