Как я перешел со Smarty на Twig

Раньше я был ярым поклонником Smarty. У Smarty достаточно много достоинств, он распространен, с ним просто, он привычен и так далее. Но так вышло, что для одного из проектов Smarty оказался слишком уж тяжелым и слегка тормозным. Я не говорю, что Smarty плох или что он негодный, нет. Просто в некоторых условиях его производительность оказалась недостаточной, и надо было искать альтернативу. Альтернатива нашлась и я очень рад, что мне выпала возможность работать с Twig.

Smarty был второй версии, в комментариях верно замечают, что третья версия имеет отличия и часто значительные.

В первую очередь я попытался подстроить Twig под синтаксис Smarty, так как тот мне был привычен, понятен и приятен. Сделать это можно, пускай и не в полной мере. Вот так:
$loader = new Twig_Loader_Filesystem('/templates');
$twig = new Twig_Environment($loader,array('charset'=>' utf -8','cache'=>'/templ_c','auto_reload'=>true));			
$escaper = new Twig_Extension_Escaper(true);
$twig->addExtension($escaper);

$lexer = new Twig_Lexer($twig, array(
  'tag_comment'  => array('{*', '*}'),
  'tag_block'    => array('{', '}'),
  'tag_variable' => array('{$', '}'),
));
$twig->setLexer($lexer);

При инициализации объявляем в массиве tag_comment, tag_block и tag_valiable. Теперь можно как в Smarty выводить переменные. При переходе достаточно удобно, но сейчас я понимаю, что лучше было бы этого не делать. Синтаксис становится неоднородным.

К некоторым вещам все же пришлось привыкать и некоторое время заглядывать в документацию, чтобы ничего не напутать. Например обход массивов
{for category in category_tree}
{$category.name}
{endfor}

Вместо
{foreach from=$category_tree item=category}
{$category.name}
{/foreach}

Обратите внимание, что в Twig не смотря на переопределение тэга переменной знак доллара перед именем переменной не ставится. Если бы не переход со Smarty — было бы удобнее.

Блоки закрываются не {/if} а {endif}. Тоже по началу путаешься.

Или, например, блоки которые не надо обрабатывать шаблонизатором.
{raw} {endraw} вместо {literal}{/literal}.

Все это мелкие подстройки и связанная с переходом адаптация. Скорее всего это даже усложнено тем, что синтаксис похож.

К чему я привык работая со Smarty?

Во-первых это структура шаблонов. Шаблоны дробились на шапку, основное тело и подвал. Также боковые блоки и другие блоки тоже иногда выделялись. Дальше все это дело подключалось в основном шаблоне в порядке следования. Теперь я понимаю, что это совсем не круто. Наследование – вот это круто! Страницы сайта зачастую построены по одному принципу, либо есть несколько типов страниц со своей организацией. Шапка/подвал везде одинаковая зачастую, а вот левое/правое меню может скакать то влево, то вправо, либо на части страниц его может не быть вовсе. В Smarty я бы стал городить условия и подключать нужный шаблон, в нем подключать еще один шаблон и так далее. В Twig все иначе. Здесь, как и в ООП шаблоны наследуются друг от друга, можно переопределять части шаблонов. Это просто здорово. Движение фактически в другую сторону – не от главного шаблона к дочерним, а отображая конечный шаблон он собирается из родителей их родителей и так до корня.
Строим основной шаблон с шапкой/подвалом, можно даже боковыми блоками, а потом наследуем от него другие шаблоны, более низкого уровня. В них запросто переопределяем боковой блок. Например, можно от основного шаблона унаследовать шаблон с левым меню и шаблон с правым меню. Что там выше, кто от кого наследуется — дело только тех, кто выше. А потом в зависимости оттого, что нам требуется – наследовать конечный шаблон либо от шаблона с правым меню, либо от шаблона с левым меню. А потом можем передумать и унаследовать шаблон не от шаблона левого меню, а от шаблона правого меню. Такая простота, прозрачность и гибкость меня очень радует. Даже кардинальные изменения даются легко. Немного кода.

Основной родительский шаблон.

main.tpl
<!doctype html>
<head>
 <title>{block html_title}Заголовок по умолчанию{endblock}</title>
</head>
<html>
<div class=”header”>Содержимое шапки</div>
<div class=”body”>
	{block content}
		Здесь ничего нет. {*Если мы не переопределим содержимое блока, то страница все равно не будет пустой.*}
	{endblock}
</div>
<div class=”footer”></div>
</html>

Теперь напишем страницу просто без меню.
left_menu.tpl
{extends "main.tpl "}
{block html_title}Главная страница{endblock} {*Переопределяем заголовок страницы*}
{block content}
 	Тут содержимое главной страницы. Это содержимое заменит определенный в родительском шаблоне текст.
{endblock}

А теперь шаблон меню с левой стороны.
left_menu.tpl
{extends "main.tpl "}
{block content}
<div class=”left_menu”>
{*Выводим список каких-то категорий*}
{for category in category_tree}
<a href=”?{$category.id}”>{$category.name}</a>
     {endfor}
</div>
<div class=”content”>
 {block page_content} {* Обратите внимание, блок не может называеться content, так как такой блок уже есть. *}
 	Здесь ничего нет. 
 {endblock}
</div>
{endblock}

И конечную страницу
{extends "left_menu.tpl "}
{block html_title}Конечная страница{endblock}
{endblock}
{block page_content}
 Содержимое страницы с меню. На этой странице переопределен заголовок страницы, заданный в самом первом, основном шаблоне.
{endblock}

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

Работая со Smarty, я привык к тому, что надо передавать все переменные в шаблон и уже там их выводить, вся обработка была в коде. Часто даже форматирование приходилось делать до шаблонизатора, в итоге выходила мешанина. В Twig можно вообще управлять логикой исполнения из шаблона, без каких либо телодвижений. Если в выводе будет не название поля, а название метода, то в этом месте будет выведено возвращаемое методом значение. Т.е. если нам надо вывести какое-то подсчитываемое значение, то его не нужно подсчитывать заранее, это будет произведено непосредственно при выводе.
// Класс пользователя
class User
{
	public function free_space()
	{
		// Что-то вычисляем, проверяем наличие свободного места.
		Return $result;
	}
}

В шаблоне вызываем:
{$user.free_space} 

И все. Не надо об этом заранее думать – все отработает и отработает быстро. Неприятным моментом было то, что если поле класса приватное, то выводить twig его не станет, даже если в классе описан геттер.

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

class My_Twig_Extension extends Twig_Extension
{
  
// Этот метод должен быть объявлен обязательно.	
  public function getFilters()
  {
    return array(    
    	'typograph => new Twig_Filter_Method($this, 'typograph')    
    );	
  }

  public function typograph($text)
  {
  	return $typograph->parse($text); // тут собственно типограф работает с передаваемым ему текстом.
  }
	
}

И подключаем его на этапе инициализации.
$twig->addExtension(new My_Twig_Extension());

Теперь шаблоне для тех переменных которые нам надо обработать – просто дописываем модификатор – {$page.content|typograph} и все, значение будет обработано. Не нужно сначала перебирать все значения до передачи их шаблонизатору и обрабатывать. Шаблонизатор все равно будет обходить массив для выхода — так это делается один раз, а не два. Расширение можно написать одно и потом дополнять его нужными функциями.

После Twig-a в сторону Smarty смотреть не очень хочется. Как то уж слишком легко и логично все получается вместе с ним.
Поделиться публикацией
Комментарии 137
    0
    По скорости замеры делали?
      –1
      Да, конечно были замеры, но сейчас у меня данных этих нет. Собственно изначально именно скорость работы была аргументом в пользу Twig.
        0
        почему не Blitz? для критичных к времени наполнения шаблона участках мы используем его.
          0
          >>почему не Blitz?

          По правде говоря я точно не помню. Blitz тоже рассматривался, но Twig почему-то победил. Может быть он оказался удобнее?
            +1
            Blitz требует куда большего участия программиста для верстки, нежели Smarty, что актуально только для больших нагрузок. В свое время отказался от него из-за больших временных затрат на крошечные изменения.
          0
          На выходе каждого шаблона twig — обычный php класс, содержащий метод render(), определяющий строчки типа echo "".$yourVar.""; внутри. В некоторых местах он даже быстрее привычной в остальных фреймворках ?php шаблонизации, ибо не использует подавление вывода.
            0
            вот почему все пользуются конкатенацией строк
            echo "".$yourVar."";

            вместо перечисления:
            echo "",$yourVar,"";

            нафига делать совершенно ненужные ёмкие операции
              +2
              Потому что конкатенация строк в php — .. Если я захочу эту строку записать в переменную вместо вывода в буфер, я просто поменяю echo на $echo = , а вам придется менять все запятые.
                0
                если крипт дебажите, то можно выводить отдельно всё что угодно и менять запятые на точки, но на продакшене зачем?
                  0
                  Назовите мне хоть одну вменяемую причину использования `,` вместо `.`.
                    +1
                    время, занимаемое конкатенацией строк + съедаемая при этом память
                      +3
                      Опять эта экономия спичек на фоне пожара.
                        0
                        ладно, убедили, на мелких проектах не важно.
                        где выводились большие объёмы данных то давало немного прироста
                          0
                          На крупных проектах тоже не важно. За свою карьеру писал более 10 крупных проектов на php. И нигде! Нигде мы не упирались в перформанс конкатенации строк!
                            0
                            и никогда не упрётесь. но можно выирать 0.1 секунды, в случае с очень большими объёмами данных больше.
                      0
                      сотни записей
                      for(...) 
                      { 
                       echo "<tr><td>".$data[$i]['cell1']."</td><td>".$data[$i]['cell2']. {...} ."</td></tr>"; 
                      }

                      совершенно бесполезное использование конкатенации
            +1
            Взял twig поле прочтения данного поста. Понравилось. Благодаря наследованию стал шаблоны использовать по образу master page из ASP.NET.
            +4
            Ни тем ни тем не пользовался, но судя по коду — Twig похож на встроенный в Django шаблонизатор, а со Smarty нужно писать кучу лишнего кода. Не совсем тогда понятно почему Smarty такой популярный, если есть такие замечательные альтернативы.
              0
              inlanger, дело не столько в лишнем коде, сколько вообще в логике работы.
              Smarty популярный из-за того, что появился давно, применялся в некоторых популярных движках и соответственно довольно много народу им пользовались, синтаксис стал привычным.
                +1
                Twig похож на встроенный в Django шаблонизатор

                jinja2 еще.
                  0
                  Разработчики и не скрывают факта похожести.
                    0
                    Более того, Twig начал разрабатывать сам автор jinja, перед тем как перейти на Python, потом его подхавтил Fabien Potencier
                  +7
                  PHP сам по себе отличный шаблонизатор, Smarty и прочие велосипеды лучше использовать только если верстальщик по другому не может.
                    +1
                    Мне сложно себе представить, как можно без костылей устроить наследование шаблонов. Все равно ведь выйдет шаблонизатор в итоге. А наследование это удобно и очень здорово.

                    Я часто сам себе верстальщик и ценю свое время и нервы.
                      –1
                      Не спорю, верстальщикам тот же Smarty очень облегчает работу, но сервер у приходится парсить шаблон, компилировать в кривой код и выполнять его. Хорошо, когда это все дело кэшируется, а если нет?

                      Что будет работать быстрее, или {$var}?
                        +19
                        Одно из самых больших заблуждений web-программистов. Не важно как быстро работают отдельные инструкции. Важно насколько они читабельны, насколько итоговый код расширяем и масштабируем! Остальное — синдром «гипероптимизации», который обычно приводит к отсутствию как читабельности, так и масштабируемости.
                          –2
                          не важно как быстро работают отдельные конструкции? А ведь автор именно по причине скорости отказался от Смарти. Так что я бы не был так уж сильно уверен.
                            –1
                            И тем не менее — прочесывать код и заменять кавычки из соображений производительности я не буду. Не из-за того, что это не влияет производительность, а из-за того, что затраченные усилия и полученный результат — не сопоставимы.
                              0
                              Прочесывать написанный код и задуматься о выборе шаблонизатора до разработки — сильно разные вещи.
                                –1
                                если на ваши сайты заходит два человека в час, то это так.
                            0
                            >>о сервер у приходится парсить шаблон, компилировать в кривой код и выполнять его.
                            О том какой код компилит Twig наверное можно отдельную статейку написать. Совсем он там не кривой.

                            >>Что будет работать быстрее, или {$var}?
                            Да много всяких вещей работают быстрее. Должен быть разумный компромисс между скоростью работы и простотой поддержки. Не быстротой единой, в общем.
                              0
                              Вы правы. Тут однозначно нельзя говорить ни в пользу чистого PHP, ни в пользу шаблонизаторов.
                                0
                                В результате все решают замеры производительности. Когда я смотрел на Twig — разница между скоростью обработки шаблонов на php и шаблонов на Twig была незначительной. А разница в удобстве — разительна.
                              0
                              twig компилирует шаблон один раз, после чего он не отличается от интерпретируемого скрипта php. Полученный скрипт потом лежит в кеше и если в шаблоне что-то изменилось кеш надо почистить.
                                0
                                Он и есть скрипт на PHP, только очень неоптимально составленный — отсюда тормоза.
                              0
                              >> Мне сложно себе представить, как можно без костылей устроить наследование шаблонов. Все равно ведь выйдет шаблонизатор в итоге. А наследование это удобно и очень здорово.

                              Наследование шаблона делается очень просто, даже без использования реальных классов. Можно использовать эту технику в «нативных» шаблонах, если скорость и объем кода критичны.
                              pyha.ru/forum/topic/4342.0
                              +1
                              PHP как шаблонизатор не справляется с основной своей задачей — отделить логику от представления. Фабиен эту тему достаточно широко раскрыл в своем блоге 2 года назад (когда начал контрибутить в twig):
                              fabien.potencier.org/article/34/templating-engines-in-php
                              fabien.potencier.org/article/35/templating-engines-in-php-follow-up
                                +2
                                Да он там лукавит до невозможности. Например, не использует короткие теги php, мотивируя это тем, что могут быть проблемы с xml. Про pascal-синтаксис тоже молчит. Необъективно.
                                  0
                                    0
                                    Ну короткие теги для РНР действительно имеют проблемы с XML и есть негласная рекомендация их не использовать из-за этого. Они могут быть как включены так и выключены на продакшне (по той же причине), а потому после нескольких деплоев, где «всё упало» я сам отвык от пратики использовать их. Но сами понимаете, это как раз малосущественно.

                                    А вот момент, когда я почувствовал, что шаблонизаторы нужны. Считается, что шаблонизаторы ограничивают разработчика, чтобы он не натворил всяких гадостей, но ведь и чистый РНР имеет одно важное ограничение: если вы используете helper'ы в виде функций, то они будут вгружены в глобальный контекст, а с этого и проблемы, они становятся доступны там где не должны быть, а самое важное, их становится трудно доопределять и переопределять под конкретные шаблоны. Если ваш код рендерит 3 шаблона и собирает их, то везде будут доступны одни и те же хелперы! Если вы меняете порядок рендеринга, то некоторые просто хелперы отвалятся. Альтернатива — использование хелперов из переменных ($routing->url_to) мне не нравится стилистически. Да и с точки зрения логики этот вариант не очень.

                                    Вообщем, Фабиен, конечно молодец, пацан слово дал, пацан слово забрал. То он сам говорил, что РНР лучший шаблонизатор, а через пару лет, понял, что был не прав.
                                      0
                                      Хэлперы в глобальном контексте? А зачем? Можно же рендерить шаблон в контексте метода и пользоваться $this для доступа к хэлперам, ну или любым другим предопределенным объектом.
                                        0
                                        Да, согласен, но $this подходит мало, ведь хедперы нужно разделять по группам, доопределять (с учетом множественного необходмисоти вгружать туда методы из многих классов), короче, получится костыль над множественным наследованием.

                                        Можно передавать классы helper'ов в переменных и впринципе, это самый правильный вариант. Юзать $routing->url(). Проблема может быть только в случае, если вы хотите передать в шаблон переменную $routing… Короче, опять таки получается проблема отделения данных от представления.
                                          +1
                                          Ну а вообще да, всё можно сделать на PHP, но проблема глобального контекста и излишней длинны языковых конструкций остается.
                                            0
                                            Всё обратно сводится к тому, что работа с шаблонами на чистом пхп требует определенной административной дисциплины, в противовес шаблонизаторам, связывающим руки «правильными» способами.
                                        +2
                                        Да где уж там негласная-то? Вот, прямо в доке и прописано:
                                        Using short tags should be avoided when developing applications or libraries that are meant for redistribution, or deployment on PHP servers which are not under your control, because short tags may not be supported on the target server. For portable, redistributable code, be sure not to use short tags.

                                        ru.php.net/manual/en/language.basic-syntax.phpmode.php
                                          –2
                                          Ну а для всех остальных случаев — негласная :)
                                            0
                                            Простите, но это выглядит как фанатизм.
                                              0
                                              В документации указано ограничение основанное на возможности отключить шорт теги на сервере. Причины делать это там не указаны. Потому даже если ты не пишешь «applications or libraries that are meant for redistribution, or deployment on PHP servers which are not under your control» стоит всё равно не стоит их использовать ибо их возможно придется отключить (даже на своем сервере) из-за проблем с XML.
                                                0
                                                Зачем их отключать на «своих» серверах? Писать <?=чтото?> приходится часто, а писать <?='<?xml.....'?> — нет. Вы же не станете в «своих» разработках использовать fsockopen вместо curl (или file_get_contents ) ) под предлогом того, что он может быть (и где-то так и есть) отключен.
                                                Вот поэтому подобные «негласные» правила и кажутся фанатизмом.

                                      –3
                                      >PHP как шаблонизатор не справляется с основной своей задачей — отделить логику от представления.

                                      А смарти и твиг капец как отделяют ее? Или циклы в шаблонах это есть отделение логики? По-моему наоборот. Мне лично проще внутри php-цикла наложить данные на кешированный где душе угодно шаблон элемента списка. При этом ни в одном шаблоне вообще нет никакой логики — только чистое представление
                                        0
                                        Не знаю как смарти, но твиг логику представления от бизнес логики отделяет на ура. В отличие от чистого PHP. На то есть объективные причины:
                                        habrahabr.ru/blogs/webdev/127906/#comment_4224465
                                          –1
                                          Ну так ведь это совершенно разные логики :-)
                                          Хотя все равно — я сторонник «академического» отделения как логики представления, так и бизнес логики от собственно самого оформления. Мухи к мухам, котлеты к котлетам. Зато у нас верстальщик может натворить шаблон зная только html, и понятия не имея о программировании, циклах, наследовании (скажите зачем вообще верстальщику это знание?) и других страшных словах.
                                      0
                                      Угу, скоро появятся шаблонизаторы для Smarty и Twig. Но пост не о том использовать шаблонизаторы для PHP или нет. Пост для тех, кто уже сделал выбор.
                                        +2
                                        Увы, PHP как язык сильно расхолаживает, а использование его в качестве шаблонизатора расхолаживает ещё больше. Нужно иметь очень сильную самодисциплину, чтобы не поддаваться искушению вынести часть бизнес-логики в шаблон, а то и вообще забить на всякое разделение.
                                        +5
                                        Я правильно понял, что автор переходил со Смарти 2 на Твиг?
                                        Смарти 3 весьма не плох, так же поддерживает большинство «плюшек» твига (вроде иерархичных блоков, циклов for, вызовов методов, etc) + имеет много своих интересных и удобных вещей.

                                        Поэтому было бы здорово почитать про сравнение Твига именно с третьей версией Смарти
                                          0
                                          >>Я правильно понял, что автор переходил со Смарти 2 на Твиг?
                                          Да, скорее всего это был Smarty2
                                          >>Смарти 3 весьма не плох
                                          Я как-то пытался на него пересесть, но у меня не получилось это быстро сделать. Надо было что-то переделывать и чуть ли не шаблоны переписывать. Может быть я просто недостаточно разобрался.
                                          В общем когда я пытался перейти со Smarty 2 на 3 — быстро не вышло и я забил.
                                          >>имеет много своих интересных и удобных вещей.
                                          А скорость работы?
                                            –1
                                            ghbvths c ,kjrfvb
                                              0
                                                0
                                                до финальной версии Смарти 3, с совместимостью шаблонов действительно были проблемы. они практически решились к 3-му релиз кандидату и полностью были решены к финальной версии.

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

                                                с момента релиза тройки было сделано много работы над увеличением производительности. субъективно, 3.0.8 не медленнее двойки (вероятно быстрее) но увеличивает скорость разработки.

                                                3.1 так же звучит многообещающе, но ждем финала.
                                              +6
                                              {for category in category_tree}
                                              {$category.name}
                                              {endfor}


                                              Вместо
                                              {foreach from=$category_tree item=category}
                                              {$category.name}
                                              {/foreach}



                                              А чем это лучше обычного php?
                                              <? foreach($category_tree as &$category): ?>
                                              <?= $category->name ?>
                                              <? endforeach; ?>


                                              php не нужно отдельно парсить.
                                              php кешируется в apc/xcache/etc.
                                              Для шаблонов на php не нужна отдельная большая библиотека, подгружаемая каждый раз. Шаблонизатор для такого подхода пишется за 10 минут и занимает 20-30 строк.

                                              Какие есть причины использовать smarty и другие шаблонизаторы вместо php?
                                                +1
                                                Ну в данном конкретном примере оно может и не слишком различается, хотя на мой взгляд одна фигурная скобка гораздо читабельнее, чем <?..
                                                >>php не нужно отдельно парсить.
                                                php кешируется в apc/xcache/etc.

                                                Также как и компилируемые шаблонизатором скрипты.
                                                >>Какие есть причины использовать smarty и другие шаблонизаторы вместо php?
                                                Наследование шаблонов как будем реализовывать? Шаблонизатор это не только замена переменных.
                                                  0
                                                  Наследование шаблонов — очень просто.

                                                  function render($template, $attributes = array()) {
                                                  extract($attributes);
                                                  ob_start();
                                                  ob_implicit_flush(0);
                                                  require "/dir/with/templates/" . $template . ".php";
                                                  ob_end_clean();
                                                  return ob_get_clean();
                                                  }


                                                  Код контроллера:

                                                  ...
                                                  render("index", array("var1" => 1, "var2" => 2));


                                                  Код подшаблона «partial»:

                                                  <?= $var2 ?>


                                                  Код шаблона index:

                                                  <?= $var1 ?>
                                                  Подгружаем подшаблон <?= render("partial", array("var2" => $var2)) ?>



                                                  Схематично, но должно быть понятно.
                                                    +1
                                                    >>extract($attributes);
                                                    У меня на extract чего-то нервный тик. :(

                                                    В итоге то что изменилось? Ну еще прилепим модификаторы потом, потом добавим песочницу, потом еще немного и в итоге все равно получится шаблонизатор. Нет разницы. Все равно шаблон компилируется один раз и дальше работает точно так же, как и написанный руками код. Но шаблоны писать проще, поддерживать проще и вообще в целом приятнее.
                                                      +2
                                                      Уважаемый, это не наследование, а инъекция. Давайте приведу понятный вам пример. У вас есть список новостей, который находится в лэйауте внутренних страниц сайта, который находится в главном лэйауте сайта. То есть, вы генерируете шаблон списка новостей, а тот сам уже себя заворачивает в специфичный лэйаут, который в свою очередь может завернуть себя в другой лэйаут и так далее. При этом, ваш шаблон списка страниц может переопределить блок (слот) в любом шаблоне (лэйауте), находящемся выше уровнем. Крайне логично, не правда ли? А теперь попробуйте мне привести пример подобного шаблона на чистом php.
                                                        0
                                                        С одной стороны согласен, чистое наследование (как тут) кода нужно больше.
                                                        Но в большинстве случаев хватает одного лейаута + возможности его переопределить. Т.е. при выводе из контроллера мы генерим шаблон, который вставляется в общий лейаут, либо передаём специфичный лейаут (например страница для печати).
                                                        Понятно, что это не сферический шаблонизатор в вакууме, но для многих задач этого вполне достаточно и прекрасно работает без особых проблем.
                                                        Если программисты не просыпаются ночью от кошмарного понимания того, что из шаблона нельзя переопределить лейаут, то я считаю нормальным такой подход.
                                                          +2
                                                          Как только вы начнете использовать модель декорации (наследования) шаблонов, вы поймете, что ЛЮБОЙ проект лучше ложиться в нее, нежели в более привычную (пока) вам схему инъекции ;-)
                                                          0
                                                          Ну а собственно при чем тут Twig? Речь идет об управлении шаблонами, а не о том, почему нельзя использовать в них PHP.

                                                          Берем
                                                          components.symfony-project.org/templating/documentation
                                                          и всё будет )

                                                          Имхо, мне кажется, изначальный пример слишком упрощен. На уровне простых циклов и условий шаблонизатор действительно не дает никаких преимуществ.
                                                            0
                                                            Как относится Templating component к шаблонному наследованию, на котором построен Twig?

                                                            Давай ты мне через 30 минут покажешь готовый рабочий пример того, что я описал выше на чистом php через Symfony\Component\Templating ;-)

                                                            Прежде чем безапелляционно заявлять что-либо, попробуй для начала сам почитать линки, которые приводишь ;-)
                                                              +1
                                                              <?php $this->extend('layout') ?>
                                                              Hello <?php echo $name ?>


                                                              Что не так? «The template engine also support multiple inheritance as explained later on.»
                                                                0
                                                                Это не наследование, а декорация. Фабиен попытался сделать его похожим на наследование в твиге, отсюда и неверное применение термина «наследование». Наследование вот: twig.sensiolabs.org/doc/templates.html#template-inheritance. Опять повторюсь — Twig построен вокруг идеи наследования — это основа шаблонизатора. Разница в том, что в декораторе из Templating component тебе всегда нужно рендерить содержимого дочерний слота, даже если тот переопределяет совсем другой блок. Рендеринг словно идет сверху вниз, когда как Twig обрабатывает шаблоны снизу вверх. Отсюда куча неучтенных мелочей типа
                                                                {% block title %}
                                                                {{ parent() }}
                                                                — News
                                                                {% endblock %}
                                                                
                                                                  0
                                                                  Ну да, ограничение в том, что даже с шаблонизатором на PHP страница будет всегда рендерится в одном и том же порядке.

                                                                  Это дейсвтительно принципиальная проблема, а как и проблема глобального контекста, от неё не избавиться никак.
                                                      –1
                                                      > Какие есть причины использовать smarty и другие шаблонизаторы вместо php?

                                                      Может быть религия?
                                                        0
                                                        Учитывая популярность шаблонизаторов, это не религия, а массовое религиозное движение
                                                          +2
                                                          Рискну предположить, что шаблонизаторы хорошо ложатся в паттерн MVC.
                                                            0
                                                            Может я плохо понимаю этот паттерн, но разве синтаксические языковые конструкции типа foreach($category_tree as &$category) — это не смешивания данных и оформления.

                                                              +1
                                                              Это распихивание данных в нужные места и вычисление позиции элементов относительно друг друга. Предлагаете строить списки с html, стилями и расчетом позиции блоков в контроллере? Это чистая работ для представления, на уровне которого и работает шаблонизатор. В представление отдается чисто информация нужная для вывода на конкретной странице, а представление подстраивается (исчезают какие-то блоки, меняется меню и прочее). Так что управление представление данных — это не смешивание данных и оформления.
                                                                0
                                                                > а представление подстраивается (исчезают какие-то блоки, меняется меню и прочее)

                                                                Вот тут не согласен. Блоки и меню — это данные, решения о том, выводить ли их — это не шаблон. В каком порядке — зависит от их веса относительно друг друга. Сортируется на уровне запроса к базе данных.
                                                                Запрещённая ссылка в меню для группы пользователей — это опять же не уровень представления.
                                                          +12
                                                          fabien.potencier.org/article/34/templating-engines-in-php
                                                          fabien.potencier.org/article/35/templating-engines-in-php-follow-up

                                                          PHP уже давно перестал быть шаблонизатором домашних страничек. Со своей современной целью (отделение представления от логики) php в качестве шаблонизатора справляется плохо. Самые явственные минусы:

                                                          1. Отсутствие песочницы. Все функции, описанные в глобальном скопе доступны из всех php «шаблонов».
                                                          2. Отсутствие наследования. Сборка шаблона сверху вниз является нелогичной для современного дизайна и контента. Сегодня на любом проекте вы верстаете сверху вниз, но выводите контент снизу вверх, что в случае с чистым php — невозможно.
                                                          3. Расширяемость. Вы можете сколько угодно доказывать, что

                                                            <? foreach($category_tree as $category): ?>
                                                                <?= $category->name ?>
                                                            <? endforeach; ?>
                                                            

                                                            То же самое, что и
                                                            {% for category in category_tree %}
                                                                {{ category.name }}
                                                            {% endfor %}
                                                            

                                                            Но вы никогда не сможете доказать, что
                                                            <? if (count($category_tree)): ?>
                                                                <? foreach($category_tree as $category): ?>
                                                                    <?= $category->name ?>
                                                                <? endforeach; ?>
                                                            <? else: ?>
                                                                No items in tree
                                                            <? endif; ?>
                                                            

                                                            Хотя бы близко столь же читаем, сколько
                                                            {% for category in category_tree %}
                                                                {{ category.name }}
                                                            {% else %}
                                                                No items in tree
                                                            {% endfor %}
                                                            


                                                          P.S.: «шорт»-тэги — зло. Об этом тысячи статей по всему интернету, так что ваш шаблон должен выглядеть вообще вот так:
                                                          <?php if (count($category_tree)): ?>
                                                              <?php foreach($category_tree as $category): ?>
                                                                  <?php echo $category->name ?>
                                                              <?php endforeach; ?>
                                                          <?php else: ?>
                                                              No items in tree
                                                          <?php endif; ?>
                                                          
                                                            –1
                                                            Цикл foreach необязательно вкладывать в условие, можно написать так:
                                                            <?php foreach($category_tree as $category): ?>
                                                                <?php echo $category->name ?>
                                                            <?php endforeach; ?>
                                                            <?php if (empty($category_tree)): ?>
                                                                No items in tree
                                                            <?php endif; ?>
                                                            

                                                            Получается ненамного длиннее.
                                                              0
                                                              Количество логического мусора на экране все-равно зашкаливает.
                                                                +3
                                                                А при попытке обойти пустой массив warning не вывалится?

                                                                И да, это таки невозможно читать и поддерживать. И это при том, что строк то всего ничего!
                                                                  –1
                                                                  Нет, это как при while(false) {}, цикл просто не выполнится.
                                                                  По поводу чтения — по-моему достаточно терпимо, пример довольно синтетический, при более больших блоках выглядит читабельнее, хотя кому как конечно :).
                                                                    +2
                                                                    >>Нет, это как при while(false) {}, цикл просто не выполнится.

                                                                    Только что попробовал — Warning: Invalid argument supplied for foreach() in
                                                                      –1
                                                                      Я имел в виду пустой массив или объект, который можно итерировать:
                                                                      conf@conf ~ $ php -d error_reporting=-1 -d display_errors=1 -r ' echo "before\n"; foreach(array() as $item) { echo $item; } echo "after\n";'
                                                                      before
                                                                      after
                                                                      conf@conf ~ $

                                                                      Остальные аргументы дадут ошибку, конечно.
                                                                        +3
                                                                        Равно как и если переменная не определена. Короче, ваш вариант не работает. Шаблонизатор сделает всё грамотнее, а кода будет меньше.
                                                                        +1
                                                                        Это если передать null и т.п., а правильнее в такой ситуации передавать пустой массив.
                                                                  0
                                                                  «шорт»-тэги — зло. Об этом тысячи статей по всему интернету


                                                                  Единственная разумная мысль по этому поводу: «трудности с деплойментом на shared-хостингах».
                                                                  Но даже эта проблема надуманная, т.к. PHP уже давно восновном ставится в качестве модуля к апачу

                                                                  Я не понимаю, почему я не должен использовать короткие теги в шаблонах?
                                                                  +2
                                                                  Имхо причина одна — запретить использование php в шаблонах. Скажем есть cms для, которой сообщество пишет шаблоны, куда надежней будет не давать писать в них php код, а ограничить их возможности. Хотя особо дотошные XSS напихают, но сервер будет целей.
                                                                  +1
                                                                  Дык наследование и в Smarty есть.
                                                                  www.smarty.net/docs/en/language.function.block.tpl
                                                                    –1
                                                                    Это наверное третья версия, да? До нее у меня руки не дошли.

                                                                    Вообще путь был таким — сначала попробовал Smarty (2), потом оказалось, что производительность не радует и начал искать альтернативу. Остановился на Twig.
                                                                      0
                                                                      Да, это появилось только в третьей версии. Но, как вы и сказали, очень удобно и гибко.
                                                                        0
                                                                        ну, если честно, это было и во второй версии, но в виде маленького расширения. на форуме смарти есть пример
                                                                        +2
                                                                        Twig у меня оказался медленнее чем Smarty3 как раз.
                                                                      0
                                                                      Работая со Smarty, я привык к тому, что надо передавать все переменные в шаблон и уже там их выводить, вся обработка была в коде.

                                                                      {$user->free_space()}

                                                                      Не?
                                                                        –2
                                                                        Я не утверждаю, что использовал все возможности Smarty, нет. Наверняка много можно было реализовать и там тоже. Но с Twig у меня получилось как-то проще и прозрачнее. А главное быстрее.

                                                                        {$user->free_space()} и {$user.free_space} в Smarty для методов и полей соответственно, верно?
                                                                        И {$user.free_space} и {$user.free_space} в Twig. Вот захочется мне потом результаты работы этого метода кэшировать в поле класса. В Smarty мне придется править шаблон (или шаблоны), а в Twig — нет. Это конечно слабенький аргумент как для определяющего при выборе шаблонизатора :).
                                                                          –1
                                                                          Если Twig определяет к методу он обращается или к свойству на этапе компиляции шаблона, то вам всё равно придётся либо очистить кэш, либо подправить шаблон чтобы изменилась его дата и он скомпилировался заново.
                                                                          Если же он определяет это на этапе выполнения, то это минус производительности (что было вашим ключевым критерием выбора).

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

                                                                          Так что действительно очень слабенький аргумент.
                                                                            0
                                                                            >>Соответственно вы потеряли либо в производительности, либо совершая такие правки вам надо помнить о необходимости перекомпиляции шаблонов

                                                                            Производительность радует, помнить ни о чем не надо, просто пользуюсь и все. Как там что под капотом — меня не очень волнует. Не то, чтобы мне совсем не интересно, но все что я знаю — Twig выполняет свою работу и выполняет качественно. Разве еще что-то нужно? Мне — нет. Хватает и других проблем которыми приходится забивать голову.

                                                                            >>Так что действительно очень слабенький аргумент.
                                                                            Да они все не очень сильные. Каждый в отдельности. А всех вместе — вполне достаточно оказалось.
                                                                              0
                                                                              И часто приходится метод делать свойством и наоборот? :)

                                                                              А по производительности всё же было бы неплохо увидеть какие-то цифры.
                                                                              Мне на самом деле вообще сложно представить условия в которых шаблонизатор становится узким местом и его производительность столь критична.
                                                                                0
                                                                                >>И часто приходится метод делать свойством и наоборот? :)
                                                                                Да нет, это из раздела приятных мелочей.

                                                                                По производительности я не возьмусь что-то оценивать. Не предвзятая и полная оценка это дело не одного дня, да и сомневаюсь я, что под силу это мне. А какие-то цифры с потолка и за уши притянутые никому не нужны и толку от них нет.
                                                                                Выше есть ссылка на сравнение шаблонизаторов, там есть цифры. Позволяют понять порядок.
                                                                                  0
                                                                                  Ага, посмотрел. Цифры там действительно интересные.
                                                                        –1
                                                                        И третье это написание собственных расширений. Часто бывают нужны какие-то функции, не реализованные в шаблонизаторе. Расширяется twig крайне просто

                                                                        С точки зрения простоты Smarty расширяется еще проще. Да, не ООП-стайл, но читаемости и функциональности это не мешает.
                                                                          0
                                                                          Не перевелись ещё люди считающие, что php == веб разработка.
                                                                            0
                                                                            Сложно разве подсветить код в топике?
                                                                              0
                                                                              Да там проставлены теги code, а как сделать красивее я не понял. Если подскажете — буду благодарен.
                                                                                0
                                                                                <source lang=«php»>
                                                                                  0
                                                                                  То есть,
                                                                                  <source lang="php">
                                                                                    0
                                                                                    Спасибо, попробую.
                                                                                    Предпросмотр, правда, не работает при редактировании топика почему-то. Но все равно попробую. Спасибо.
                                                                                      0
                                                                                      Там где просто html можно использовать
                                                                                      <source lang="html">
                                                                                        0
                                                                                        Я понял, спасибо.
                                                                              0
                                                                              Раньше я был ярым поклонником Smarty. У Smarty достаточно много достоинств, он распространен, с ним просто, он привычен и так далее. Но так вышло, что для одного из проектов Smarty оказался слишком уж тяжелым и слегка тормозным.
                                                                              и тогда я перешел на blitz
                                                                              статей про блиц на Хабре предостаточно, но если есть пожелания Хабровчан, могу по подробнее рассказать про этот шаблонизатор
                                                                                0
                                                                                Лично мне было бы интересно сравнение с тем же Smarty. Распространенный и понятных многим шаблонизатор. Наверняка есть отличия в работе.
                                                                                  0
                                                                                  блица или твига?
                                                                                  Основное отличие — это исполняемый модуль, по этому производительность выше раз в 10.
                                                                                  Отличие по синтаксису: — нет плагинов, но есть кэлбэки.
                                                                                  В целом там немного другой подход к шаблонизации
                                                                                    0
                                                                                    Сравнение blitz и Smarty.
                                                                                      0
                                                                                        0
                                                                                        Что-то не видно там примеров применения и сравнения подходов, синтаксиса или еще чего-то подобного. А нужно как раз это. Один график — не сравнение.
                                                                                  +1
                                                                                  В Blitz очень много логики вывода перекладывается на контроллер. Конечно он быстрее всего чего можно (так как на C), но он почти ничего не умеет делать. С горем пополам мне удалось реализовать на нём подобие наследования с одним уровнем вложенности, это хотя бы немного упростило процесс разработки…

                                                                                  В общем, сейчас я считаю использование Blitz неорпавданным даже для высоконагруженных проектов. Не представляю себе систему, в которой работа с БД происходла бы быстрее генерации страницы из скомпилированного шаблона.
                                                                                    0
                                                                                    для высоконагруженных речь идёт не только о вкладе в latency, но и о нагрузке процессоров веб-кластера.
                                                                                +1
                                                                                Когда после python (связка cherrypy+sqlalchemy+jinja2) пришлось писать проект на пыхе, я решил таки в нем воспользоваться каким нибудь шаблонизатором. В очередной раз взглянув на синтаксис шаблонов Smarty испытал рвотный рефлекс. Случайно наткнулся та Twig, и радости моей не было предела.
                                                                                  0
                                                                                  Слава Богу в свое время я перешел на Питон.
                                                                                    0
                                                                                    Чтобы не вводить читателей в заблуждение, я думаю стоит указать в статье, что вы сравниваете устаревшую версию Smarty с современным Twig, а так же о том, что в Smarty 3 (которому, к слову, уже больше года) описанные вами синтаксические недостатки всё-таки были исправлены.
                                                                                      0
                                                                                      Готово. Написал, что Smarty второй версии. Что там в третьей писать не буду — не знаю.
                                                                                      Да и не очень хочу.
                                                                                        +1
                                                                                        Это по крайней мере странно. Вы постарались сделать из Twig «почти» Smarty, чтобы вам было удобнее. Однако игнорируете факты, что описанные вами проблемы не касаются Smarty 3, для которого привычный вам синтаксис — родной.
                                                                                          0
                                                                                          Ничего странного в этом нет. Когда осуществлялся переход — я работал со Smarty2. Я к нему привык, работал с ним долго и он мне как родной стал. Синтаксис Smarty мне был привычен и я естественно пытался минимизировать проблемы по адаптации для себя. Пытался использовать Smarty3, но мне это не удалось. Может быть из-за того, что в то время он был еще не стабилен. Не вчера это было, а весьма давненько. Соответственно и тесты я проводил на второй версии, опирался на результаты вот того топика что выше (по второй версии результаты были вполне сопоставимы с моими) и выбрал Twig, Мне понравилось и возвращаться к Smarty у меня желания уже нет.
                                                                                      +4
                                                                                      Провёл небольшое сравнение производительности Smarty 3.0, 3.1 RC1 и последней версии Twig. Тестировал базовые возможности: вставка значений переменных и циклы. В шаблоне вставляется значение 1000 переменных, а так же в цикле выводится содержимое массива из 1000 элементов. Результаты очень интересны.
                                                                                      Компиляция шаблона:
                                                                                      Twig: 0.17 секунд
                                                                                      Smarty 3.0.8: 1.86 секунд
                                                                                      Smarty 3.1 RC1: 1.83 секунды

                                                                                      Да, медленно. Во время разработки придётся потерпеть. Но например меня больше всего интересует производительность в бою, когда сайт не в разработке, а уже работает. Очень важно, чтобы компилятор шаблона сделал свою работу качественно, и скомпилированный шаблон работал максимально быстро.
                                                                                      Итак, скорость работы скомпилированного шаблона:
                                                                                      Twig: 0.132 секунды
                                                                                      Smarty 3.0.8: 0.021 секунда
                                                                                      Smarty 3.1 RC1: 0.014 секунд

                                                                                      То есть Smarty 3.0.8 в 6 раз быстрее, чем Twig. Smarty 3.1 RC1 — в 9!
                                                                                      Может быть я в чём-то ошибся, поэтому выкладываю архив с тестами: smarty_vs_twig.7z (169 кб., всё включено).
                                                                                      Прошу более компетентных в Twig проверить мой код — где я мог допустить ошибку?
                                                                                        +1
                                                                                        Изучил скомпилированные версии шаблонов, и обнаружил, что Twig по умолчанию экранирует данные, на что он конечно же тратит время. Отключил экранирование ('autoescape' => false), получил 0.071 секунду в предыдущем тесте. То есть всё равно в 4-5 раз медленнее, чем Smarty.
                                                                                        Ещё интересным показалось то, что Smarty 3 объединяет всю цепочку из наследуемых шаблонов в один большой и затем компилирует, будто изначально и не было никакого наследования. То есть в результате при использовании наследования вообще не будет потерь производительности! К слову, при возможности Smarty 3 так же поступает с инклюдами.
                                                                                        Twig же старательно создал для каждого шаблона по красивому классу и файлу. И при каждой генерации страницы загружает всё это добро.
                                                                                          0
                                                                                          статья заимела обратный эффект: тоже подумывал о переходе на твиг со смарти3, но теперь, думаю, отложу эту идею :)
                                                                                            0
                                                                                            Почему обратный? Не было задачи кого-то переманить или еще что. Просто мой опыт, возможно он будет кому-то полезен. А если она кого-то предостерегла от ошибочного шага (если он ошибочный) — тем лучше. Разве это плохо?
                                                                                          0
                                                                                          Какие-то уж больно синтетические тесты. Сложно по ним реально что-то оценивать. Надо очень пристально на это дело смотреть.
                                                                                          +1
                                                                                          кстати, в смарти можно писать более привычно {foreach $ololo as $key=>$value}{/foreach}

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

                                                                                          Самое читаемое