📜 ⬆️ ⬇️

How I switched from Smarty to Twig

I used to be an ardent fan of Smarty. Smarty has a lot of advantages, it’s common, it’s simple, it’s usual and so on. But it turned out that for one of the projects Smarty turned out to be too heavy and slightly inhibitory. I'm not saying that Smarty is bad or that it is worthless, no. Just in some conditions, its performance was insufficient, and it was necessary to look for an alternative. An alternative was found and I am very glad that I had the opportunity to work with Twig.

Smarty was the second version, in the comments correctly notice that the third version has differences and often significant.

First of all, I tried to tweak Twig under the Smarty syntax, as I was used to it, understandable and enjoyable. You can do it, albeit not fully. Like this:
$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); 

During initialization, we declare in the tag_comment, tag_block and tag_valiable array. Now you can display variables in Smarty. During the transition it is quite convenient, but now I understand that it would be better not to do this. The syntax becomes patchy.

Some things still had to get used to and look at the documentation for a while so as not to mess up anything. For example, traversing arrays
 {for category in category_tree} {$category.name} {endfor} 

Instead
 {foreach from=$category_tree item=category} {$category.name} {/foreach} 

Note that in Twig, in spite of the variable tag redefinition, the dollar sign is not placed before the variable name. If it were not for the transition from Smarty - it would be more convenient.
')
Blocks do not close {/ if} but {endif}. Also at first you get confused.

Or, for example, blocks that do not need to be processed with a template engine.
{raw} {endraw} instead of {literal} {/ literal}.

All these are minor adjustments and adaptation related to the transition. Most likely this is even complicated by the fact that the syntax is similar.

What am I used to working with Smarty?

First is the pattern structure. The templates were divided into cap, main body and basement. Also, side blocks and other blocks also sometimes stood out. Then the whole thing was connected in the main template in the order. Now I understand that this is not cool at all. Inheritance is awesome! Pages of the site are often built on the same principle, or there are several types of pages with their organization. The cap / basement is often the same everywhere, but the left / right menu can jump to the left, then to the right, or it may not be part of the pages. In Smarty, I would fence the conditions and connect the desired template, connect another template in it, and so on. Twig is different. Here, as in OOP, patterns are inherited from each other, you can redefine portions of patterns. This is just great. The movement is actually in the other direction - not from the main template to the children, but by displaying the final template, it is collected from the parents of their parents and so on to the root.
We build the main template with a header / basement, you can even use side blocks, and then we inherit from it other templates of a lower level. They easily redefine the side block. For example, you can inherit from the main template a template with a left menu and a template with a right menu. What is there higher, who is inherited from whom - the case of only those who are higher. And then, depending on what we need, is to inherit the final template either from the template with the right menu or from the template with the left menu. And then we can change our mind and inherit the template not from the template of the left menu, but from the template of the right menu. Such simplicity, transparency and flexibility make me very happy. Even drastic changes are made easy. Some code.

The main parent template.

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> 

Now we will write the page simply without a menu.
left_menu.tpl
 {extends "main.tpl "} {block html_title} {endblock} {*  *} {block content}    .        . {endblock} 

And now the menu template on the left side.
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} 

And the final page
 {extends "left_menu.tpl "} {block html_title} {endblock} {endblock} {block page_content}    .      ,    ,  . {endblock} 

As a result, the final templates are not cluttered with connections, conditions and everything else. Just say what we inherit from the template, and then only as a matter of fact.

Working with Smarty, I got used to the fact that it is necessary to transfer all variables to a template and display them there, all processing was in code. Often, even the formatting had to be done before the template engine, as a result, there was a hodgepodge. In Twig, you can generally control the execution logic from a template, without any gestures. If the output is not the name of the field, but the name of the method, then the value returned by the method will be displayed in this place. Those. if we need to display some calculated value, then it does not need to be calculated in advance, it will be done directly during the output.
 //   class User { public function free_space() { // - ,    . Return $result; } }   : {$user.free_space} 

And that's all. No need to think about it in advance - everything will work out and work out quickly. The unpleasant moment was that if the class field is private, then twig will not output it, even if a getter is described in the class.

And the third is writing your own extensions. Often you need some functions that are not implemented in the template engine. Twig expands extremely easy. For example, we need to print the output. Selectively.

 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); //        . } } 

And we connect it at the initialization stage.
 $twig->addExtension(new My_Twig_Extension()); 

Now the template for the variables we need to process is simply adding a modifier - {$ page.content | typograph} and that's it, the value will be processed. You do not need to first iterate over all values ​​before passing them to the template engine and process them. The template engine will still bypass the array to exit - this is done once, not two. You can write one extension and then add it with the necessary functions.

After Twig-a, I don’t really want to look at Smarty. As it is too easy and logical, everything turns out with it.

Source: https://habr.com/ru/post/127906/


All Articles