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

Шаблонизаторы для PHP, обзор принципов.

Время на прочтение6 мин
Количество просмотров2K
У таких статей обычно плохая судьба на Хабре.
«Шаблонизаторы», в особенности «шаблонизаторы для PHP» — встретив эти слова в заголовке темы на форуме, названии статьи или записи в блоге, можно быть уверенным — очередной холивар где-то рядом. В чем причина?

  1. Выбор. Шаблонизаторов для РНР не много, а очень много. Некоторые реализуются в нативном PHP коде, другие — в С-расширениях. Многие из них отличаются друг от друга лишь мелочами или статистическими параметрами(кеширование есть/нет, время обработки, время выполнения и.т.д.), многие являются облегченными аналогами уже известных шаблонизаторов, некоторые — их оптимизированными версиями.
  2. Разные принципы работы. В основе самых известных шаблонизаторов лежат абсолютно разные принципы(о них я и хочу поговорить в этой статье). Вспомните, насколько отличаются Smarty и Blitz по принципу обработки конструкций и логических условий, но назвать каждый из этих принципов ущербным или недостаточным язык не поворачивается.
  3. Обе этих причины рождают собственно основную причину возникновения холиваров: самодостаточность. Если бы мы имели по одному шаблонизатору на один принцип, а не по 10-15, как сейчас, это был бы безусловный плюс. Но, когда путем манипуляций с известными принципами работы шаблонизаторов и их незначительного изменения рождается новый, самодостаточный шаблонизатор — он завоевывает себе некоторую известность, и появляется N-ная сторона в противостоянии программистов.

Лебедь, Рак и Щука, не находите? Все тянут в свою сторону, но указать на явные функциональные недостатки какого-либо подхода одного шаблонизатора невозможно — его сторонники всегда найдут метод реализации данной функциональности, и спор опять уходит в бесконечный флейм.
Теперь, собственно зачем я пишу эту статью. Мне хотелось бы осветить некоторые виды шаблонизаторов с точки зрения их синтаксиса и уровня гибкости, предоставляемого как программисту, так и кодеру(так я буду называть человека, работающего с шаблоном для Веб-приложения).

Я не буду подробно рассматривать представителей каждого вида, только приведу необходимые мне примеры кода.Для определенности, мы будем рассматривать самого обычного заказчика. Это частное лицо, например системный администратор небольшой конторы, не владеющий языками программирования, но легкообучаемый, являющийся одновременно и веб-мастером и кодером проекта. И это не сферический клиент в вакууме — таких большинство. Если не людей, то требований к дизайну сайта — «чтобы можно было легко потом поменять»

-1) Pure PHP

Хоть я и присвоил чистому РНР коду отрицательный индекс, это сделано лишь для того чтобы четко обозначить позицию, которой я придерживаюсь:
для заказчика это темный лес, который изучать ему нет никакой необходимости, по причине того, что синтаксис любого языка программирования рассчитан на максимальную гибкость, и потому избыточен, что для шаблонизатора является самым страшным пороком.Как бы не облегчались конструкции в шаблонизаторах, основанных на PHP синтаксисе, конструкции foreach, for, if и все остальные достойны сокращения.
Я не буду брать Zend_Framework в качестве примера, а возьму достаточно развитый и амбициозный проект, Savant3:
<html>
<table>
    <?php while ($row = $this->result->fetchRow()): ?>
        <tr>
            <?php foreach ($row as $val): ?>
                <td><?php $this->_($val) ?></td>
            <?php endforeach; ?>
        </tr>
    <?php endwhile; ?>
</table>
</html>
Это нативный PHP-код, но понимание строк while ($row = $this->result->fetchRow()): и foreach ($row as $val): требует комлексных навыков в PHP. И это главный контраргумент к заявлениям типа «РНР сам по себе отличный шаблонизатор, зачем изобретать велосипед?». Затем, чтобы не учить заказчика кататься на одноколесном, на котором программисты могут творить чудеса, а дать что-нибудь попроще и поустойчивей к синтаксическим вольностям — трехколесный например. Мы предположили ранее, что для нашего клиента это именно тот самый уровень.
Перейдем непосредственно к шаблонизаторам. Нумерацию, по традиции, начнем с нуля.</p

0) Interpreter In Interpreter(3I)

Безусловно, самый известный — это Smarty. И более абстрагированный, но, на мой взгляд, с более неоднозначным синтаксисом ETS. А PEAR представляет неплохой класс PEAR::HTML_Template_Flexy. Их первая проблема в том, что, как совершенно верно замечают противники Smarty, многие конструкции выглядят аналогичным образом и в PHP-коде, а более сложные задачи, в которых проявляются сильные отличия Smarty от PHP, попадаются достаточно редко. Например код из примеров PEAR::HTML_Template_Flexy:
{ucfirst(#this is the header#)}

{includeBody():h}

{foreach:a,k,v}
  k is {k}, and v is {v}
{end:}

{if:showStuff}Hello{end:}
{if:showDog()}Doggy{end:}
И Smarty и любой подобный шаблонизатор выглядит избыточным, с этим глупо спорить. Как не называй — тяжелый, медленный, перегруженный, но Smarty именно такой. Подобные шаблонизаторы пишутся программистами и для программистов. Если команда работает над каким-либо проектом, то, безусловно, такой гибкий синтаксис «дополнительного языка» и возможность перенесения части логики внутрь шаблона очень сильно упрощают разработку.Но как только проект передается в руки людей, не ознакомленных с синтаксисом такого шаблонизатора — никакая документация и туториалы не спасут. А если и сам шаблонизатор написан из рук вон плохо — то уловить логику с первого взгляда вообще невозможно.Хоть ETS и не похож на PHP в чистом виде, но он обладает сложным синтаксисом, в некоторых деталях похожим на Smarty. Тем, кто никогда не видел ETS, приведу вот этот кусок кода без комментариев:
{mask:main}
<html>
    <head><title>{title}</title></head>
    <body>
          <h1>{title}</h1><hr>
          {mask:mypartners}
                {mask://partners}
                      <b>{if: {id} == {../../id} }<p>{label}</p>{/if}</b>
                {/mask}
          {/mask}
    </body>
</html>
{/mask}
Я извиняюсь за излишнее внимание, уделенное именно Smarty, суть не в моем отношении к нему, а в его однозначном преобладании в секторе рассматриваемых шаблонизаторов.

1) Block&Var

На самой заре шаблонизаторов, когда они только отделились от PHP-кода, этот тип преобладал. К ним можно отнести: OO Template, PEAR::HTML_Template_IT, Blitz, TemplatePower, Yapter и их ещё очень много. Когда я писал эту статью, откопал старый(больше 2-х лет) список 25-ти шаблонизаторов(в нем можно найти некоторые из приведенных здесь названий), датированный 2006 годом. В течении 2007-2008 гг. огромную популярность обрел MVC паттерн(а с ним и всякие рельсоподобные фреймворки), и блочные шаблонизаторы в него совершенно не вписывались, т.к. предпологали дополнительный код в controller'е, отвечающий за циклические и условные блоки. И очень показательно, что многие из ссылок, приведенных в этом обзоре не работают. Эти шаблонизаторы морально устарели, на фоне современных технологий построения веб-приложений, в обзорах их чаще всего называют «классикой», но в них заложен очень сильный принцип взаимодействия программа<=>представление(намеренно не называю логикой, впоследствии могут быть разночтения), который я хочу рассмотреть подробнее.Возьмем код Blitz:
    {{ BEGIN item }}
        hello, world
    {{ END }}
И соответствующий ему код на PHP:
<?
$T = new Blitz('tpl');
$T->iterate('/item');
echo $T->parse();
?>
Что делает этот код? Просто выводит текст «hello, world». Ничего больше, но вот важная особенность таких шаблонизаторов: никакими усилиями из шаблонизатора нельзя изменить суть выполняемых операций. То есть, если не прикапываться к термину «логика представления»(о нем позже), она целиком зависит от программы! Т.е. в сущности, у кодера нет никакого контроля над шаблоном — власть в виде блоков призрачна. Возьмем теперь ETS:
{repeat: <b>n</b>}
hello, world
{/repeat}
А здесь все совершенно наоборот, прямо в шаблоне имеется возможность управлять циклом. Так же и с логическими условиями. Если кодер шаблона Blitz захочет отобразить блок «hello, world» 7 раз, ему придется звать на помощь программиста, т.к. эта опция находится непосредственно в программе. Если кодер шаблона ETS захочет сделать тоже самое, он сможет это сделать самостоятельно, прямо в шаблоне.За такую свободу кодер платит изучением синтаксиса Smarty или ETS. А если не хочет платить — сильно ограничивается принципами работы блочных шаблонизаторов. А существующие симбиозы блочных и интепретируемых шаблонизаторов в подавляющем большинстве имеют ужасный синтаксис и не менее ужасную реализацию.

2) Tag-based

Это шаблонизаторы основанные на HTML-тегах или их производных, например bTemplate, PEAR::HTML_Template_Flexy(подходит сразу под две категории). Здесь я не буду сильно распространяться, только выделю два типа шаблонизаторов:
  • Дополняющие шаблон специальными тегами
    Оперирующие существующей HTML структурой шаблона

    Первые не представляют ровным счетом никакого интереса, т.к. в большинстве реализаций являются измененным видом шаблонизаторов 0 типа. Тем, кто никогда не видел таких шаблонизаторов, хватит этого куска кода из bTemplate:
Теги:
Хабы:
+3
Комментарии7

Публикации

Изменить настройки темы

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн