Twig, los mejores trucos y técnicas avanzadas
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
10,625
On Slideshare
4,769
From Embeds
5,856
Number of Embeds
28

Actions

Shares
Downloads
198
Comments
0
Likes
9

Embeds 5,856

http://www.symfony.es 3,428
http://desymfony.com 1,061
http://blog.liip.ch 720
https://blog.liip.ch 230
http://www.desymfony.com 129
http://symfony.es 122
http://desymfony.es 48
http://librosweb.es 24
http://www.aggregator.ch 15
http://symfony.local 11
http://desymfony.local 10
http://translate.googleusercontent.com 7
http://www.desymfony.es 7
http://www.newsblur.com 7
http://desymfony.eu 6
http://192.168.11.11 6
http://www.sfexception.com 5
http://amphibiology1.rssing.com 5
http://reader.feedshow.com 3
http://192.168.11.10 3
http://news.php-homepage.de 2
http://www.linkedin.com 1
http://ranksit.com 1
http://desymfony.acilia.es 1
http://feeds.liip.ch 1
http://diysdk.schlund.de 1
http://planet.freeflux.net 1
https://www.linkedin.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Twig, los mejores trucos ytécnicas avanzadasJavier EguíluzUniversitat Jaume I · Castellón · 15-16 junio 2012 · desymfony.com
  • 2. ¡muchas gracias a nuestros patrocinadores! PATROCINADOR PLATINOPATROCINADORES OROPATROCINADORES PLATAPATROCINADORES BRONCE
  • 3. Agenda • Buenas prácticas • Técnicas avanzadas • Trucos y cosas nuevas
  • 4. CódigoEl código fuente de los ejemplosmás avanzados de esta ponenciaestá disponible en:https://github.com/javiereguiluz/desymfony!twig
  • 5. PERSONALIZACIÓN EXTREMA DE FORMULARIOS1.* BÁSICO INTERMEDIO AVANZADO
  • 6. <div> {{ form_label(form.nombre) }} {{ form_errors(form.nombre) }} {{ form_widget(form.nombre) }}</div>
  • 7. {% extends ::base.html.twig %}{% form_theme form _self %}{% block integer_widget %} <div class="integer_widget"> {% set type = type|default(number) %} {{ block(field_widget) }} </div>{% endblock %}{% block content %} {# render the form #} {{ form_row(form.age) }}{% endblock %}
  • 8. {% extends ::base.html.twig %}{% form_theme form _self %}{% block integer_widget %} <div class="integer_widget"> {% set type = type|default(number) %} {{ block(field_widget) }} </div>{% endblock %}{% block content %} {# render the form #} {{ form_row(form.age) }}{% endblock %}
  • 9. {% extends ::base.html.twig %}{% form_theme form _self %}{% block integer_widget %} <div class="integer_widget"> {% set type = type|default(number) %} {{ block(field_widget) }} </div>{% endblock %}{% block content %} {# render the form #} {{ form_row(form.age) }}{% endblock %}
  • 10. {% form_theme form _self %}{% block _formulario_nombre_widget %} <div class="especial"><strong> {{ block(field_widget) }} </strong></div>{% endblock %}{{ form_widget(form.nombre) }}
  • 11. {% form_theme form _self %}{% block _formulario_nombre_widget %} <div class="especial"><strong> {{ block(field_widget) }} </strong></div>{% endblock %}{{ form_widget(form.nombre) }}
  • 12. class UsuarioType extends AbstractType{ public function buildForm(FormBuilder $builder, array $options) { $builder ->add(nombre) ->add(apellidos) ->add(email) ->... ->add(ciudad) ; } public function getName() { return cupon_backendbundle_usuariotype; }}
  • 13. class UsuarioType extends AbstractType{ public function buildForm(FormBuilder $builder, array $options) { $builder ->add(nombre) ->add(apellidos) ->add(email) ->... ->add(ciudad) ; } public function getName() { return cupon_backendbundle_usuariotype; }}
  • 14. <strong>Label</strong>: Valor
  • 15. <strong>Label</strong>: Valor<strong>{{ form.nombreCampo.vars.label }}</strong>:{{ form. nombreCampo.vars.value }}
  • 16. <strong>Label</strong>: Valor<strong>{{ form.nombreCampo.vars.label }}</strong>:{{ form. nombreCampo.vars.value }}
  • 17. CONSTANTES1.* BÁSICO INTERMEDIO AVANZADO
  • 18. {{ constant() }}
  • 19. {{ constant(SymfonyComponentHttpKernelKernel::VERSION) }}
  • 20. {{ constant(SymfonyComponentHttpKernelKernel::VERSION) }}namespace SymfonyComponentHttpKernel;abstract class Kernel implements KernelInterface{ // ... const VERSION = 2.0.15;}
  • 21. namespace SymfonyComponentHttpKernel;abstract class Kernel implements KernelInterface{ // ... const VERSION = 2.1.0-DEV; const VERSION_ID = 20100; const MAJOR_VERSION = 2; const MINOR_VERSION = 1; const RELEASE_VERSION = 0; const EXTRA_VERSION = DEV;}
  • 22. REDEFINE LOS FILTROS POR DEFECTO1.* BÁSICO INTERMEDIO AVANZADO
  • 23. {{ array|sort }}
  • 24. asort() array_multisort()arsort() natcasesort()krsort() natsort()ksort() rsort()rsort() shuffle()shuffle() uasort()sort() uksort()usort()
  • 25. ¿Dónde se definenlos filtros, etiquetas y tags de Twig?
  • 26. lib/twig/Extesion/Core.phpclass Twig_Extension_Core extends Twig_Extension { public function getTokenParsers() { return array( new Twig_TokenParser_For(), new Twig_TokenParser_If(), new Twig_TokenParser_Extends(), new Twig_TokenParser_Include(), new Twig_TokenParser_Block(), // ... ); } public function getFilters() { $filters = array( format => new Twig_Filter_Function(sprintf), replace => new Twig_Filter_Function(strtr), abs => new Twig_Filter_Function(abs),
  • 27. {{ array|sort }}/** * Sorts an array. * * @param array $array An array */function twig_sort_filter($array){ asort($array); return $array;}
  • 28. natcasesort()a0, A1, a2, a10, ...
  • 29. class MiCoreExtension extends Twig_Extension_Core { // ...}
  • 30. class MiCoreExtension extends Twig_Extension_Core { public function getFilters() { // ... }}
  • 31. class MiCoreExtension extends Twig_Extension_Core { public function getFilters() { return array_merge( parent::getFilters(), array( ... ) ); }}
  • 32. $twig = new Twig_Environment($loader, array( ... ));$twig->addExtension(new MiCoreExtension());
  • 33. class MiCoreExtension extends Twig_Extension_Core{ public function getFilters() { return array_merge(parent::getFilters(), array( sort => new Twig_Filter_Method($this, sortFilter) )); } public function sortFilter($array) { natcasesort($array); return $array; }}
  • 34. {{ array|sort }}function twig_sort_filter($array){ natcasesort($array); return $array;}
  • 35. TODO SON EXPRESIONES1.5 BÁSICO INTERMEDIO AVANZADO
  • 36. {% include seccion_ ~ oferta.categoria ~ .twig %}{% for i in (1+3)//2..2**(3-1) %}{% endfor %}
  • 37. {% set ofertas = { (oferta ~ oferta.id): ..., (3 ~ _ ~ oferta.nombre|length): ..., (2**2+1): ...} %}
  • 38. {% set ofertas = { (oferta ~ oferta.id): ..., (3 ~ _ ~ oferta.nombre|length): ..., (2**2+1): ...} %}
  • 39. {% set ofertas = { oferta7040: ..., 3_57: ..., 5: ...} %}
  • 40. EMBED1.8 BÁSICO INTERMEDIO AVANZADO
  • 41. {% include %} {% extends %} {% embed %}
  • 42. {% include ... %}
  • 43. {% extends ... %}
  • 44. {% embed ... %}
  • 45. {% embed "lateral.twig" %} {% block principal %} ... {% endblock %}{% endembed %}
  • 46. {% embed "lateral.twig" %} {% block secundario %} ... {% endblock %}{% endembed %}
  • 47. {% include plantilla.twig %}{% embed plantilla.twig %}{% endembed %}
  • 48. ESCAPING AUTOMÁTICO1.8 BÁSICO INTERMEDIO AVANZADO
  • 49. {% filter escape(js) %} <script type="text/javascript"> var texto = "<p>Lorem ipsum dolor sit amet</p>"; alert(texto); </script>{% endfilter %}{% filter escape(html) %} <script type="text/javascript"> var texto = "<p>Lorem ipsum dolor sit amet</p>"; alert(texto); </script>{% endfilter %}
  • 50. x3cscript typex3dx22textx2fjavascriptx22x3ex0avar texto x3d x22x3cpx3eLorem ipsum dolor sit ametx3cx2fpx3ex22x3bx0a alertx28textox29x3bx0ax3cx2fscriptx3ex0a&lt;script type=&quot;text/javascript&quot;&gt; var texto = &quot;&lt;p&gt;Lorem ipsum dolor sit amet&lt;/p&gt;&quot;; alert(texto);&lt;/script&gt;
  • 51. {{ variable|e }}{{ variable|e(html) }}{{ variable|escape(js) }}{{ variable|e(js) }}{% autoescape %} ........... {% endautoescape %}{% autoescape html %} ... {% endautoescape %}{% autoescape js %} ....... {% endautoescape %}{% autoescape false %} .... {% endautoescape %}
  • 52. $twig = new Twig_Environment($loader, array( autoescape => function($nombre_plantilla) { return decide_escape($nombre_plantilla); }));
  • 53. $twig = new Twig_Environment($loader, array( autoescape => function($nombre_plantilla) { return decide_escape($nombre_plantilla); }));function decide_escape($plantilla) { $extension = substr($plantilla, strrpos($plantilla, .) + 1); switch ($extension) { js: return js; default: return html; }}
  • 54. RANDOM1.6 BÁSICO INTERMEDIO AVANZADO
  • 55. {{ random() }}
  • 56. {{ random() }}{{ random(10) }}
  • 57. {{ random() }}{{ random(10) }}{{ random("abcde") }}
  • 58. {{ random() }}{{ random(10) }}{{ random("abcde") }}{{ random([a, b, c]) }}
  • 59. FUNCIONES DINÁMICAS1.5 BÁSICO INTERMEDIO AVANZADO
  • 60. the_ID()the_title()the_time()the_content()the_category()the_shortlink()
  • 61. the_ID()the_title()the_time()the_content()the_category()the_shortlink()
  • 62. the_ID()the_title()the_time()the_content()the_category()the_shortlink()the_*()
  • 63. $twig->addFunction( the_*, new Twig_Function_Function(wordpress));function wordpress($funcion, $opciones){ // ...}
  • 64. $twig->addFunction( the_*, new Twig_Function_Function(wordpress));function wordpress($funcion, $opciones){ // ...}
  • 65. {{ the_ID() }}
  • 66. {{ the_ID() }}function wordpress(ID, array()) { ... }
  • 67. {{ the_ID() }}function wordpress(ID, array()) { ... }{{ the_content() }}
  • 68. {{ the_ID() }}function wordpress(ID, array()) { ... }{{ the_content() }}function wordpress(content, array()){ ... }
  • 69. {{ the_title(<h3>, </h3>) }}function wordpress(title, array( <h3>, </h3>)) { ... }
  • 70. *_*_link()next_image_link()next_post_link()next_posts_link()previous_image_link()previous_post_link()previous_posts_link()
  • 71. php_*()
  • 72. FILTROS DINÁMICOS1.5 BÁSICO INTERMEDIO AVANZADO
  • 73. {{ now|fecha_corta }}{{ now|fecha_larga }}fecha_*()
  • 74. $twig->addFilter( fecha_*, new Twig_Filter_Function(fecha));function fecha($funcion, $opciones){ // ...}
  • 75. VARIABLES GLOBALES1.* BÁSICO INTERMEDIO AVANZADO
  • 76. {{ app.security }}{{ app.user }}{{ app.request }}{{ app.session }}{{ app.environment }}{{ app.debug }}
  • 77. {{ _charset }}{{ _context }}{{ _self }}
  • 78. {{ _charset }} UTF-8
  • 79. {{ _context }}{% for i in _context|keys %} {{ i }}{% endfor %}
  • 80. {{ _context }}{% for i in _context|keys %} {{ i }} app assetic{% endfor %} _parent oferta ciudad_por_defecto ciudadSeleccionada expirada ...
  • 81. {{ _context }}{% for i in _context|keys %} {{ i }} app assetic{% endfor %} _parent oferta ciudad_por_defecto ciudadSeleccionada expirada ...
  • 82. {{ _context }}{{ variable|mi_filtro(_context) }}
  • 83. {{ _context }}{{ variable|mi_filtro(_context) }} SÓLO SI NO HAY OTRO REMEDIO
  • 84. {{ _self }}Twig_Template
  • 85. {{ _self }}{{ _self.getTemplateName }}OfertaBundle:Default:includes/oferta.html.twig
  • 86. {{ _self }}{{ _self.blocks|keys|join(", ") }}title, stylesheets, rss, javascripts,id, body
  • 87. {{ _self }}{{ _self.blocks|keys|join(", ") }}title, stylesheets, rss, javascripts,id, body SÓLO SI NO HAY OTRO REMEDIO
  • 88. EL SANDBOX1.* BÁSICO INTERMEDIO AVANZADO
  • 89. DEMO
  • 90. DATE1.6 BÁSICO INTERMEDIO AVANZADO
  • 91. {{ now|date("d/m/Y H:i:s") }}{{ now|date("d/m/Y H:i:s", "America/Argentina/Buenos_Aires") }}{{ now|date("d/m/Y H:i:s", "America/Havana") }}{{ now|date("d/m/Y H:i:s", "America/Caracas") }}{{ now|date("d/m/Y H:i:s", "America/Lima") }}
  • 92. España: 11/06/2012 10:45:22Argentina: 11/06/2012 05:45:22Cuba: 11/06/2012 04:45:22Venezuela: 11/06/2012 04:15:22Perú: 11/06/2012 03:45:22
  • 93. $twig = new Twig_Environment($loader);$twig->getExtension(core) ->setDateFormat(d-m-Y H:i:s, %d días);$twig->getExtension(core) ->setTimezone(America/Montevideo);
  • 94. date()
  • 95. {{ date() }}
  • 96. {{ date() }}{{ date()|date() }}
  • 97. {{ date() }}{{ date()|date() }}{{ date()|date("d/m/Y") }}
  • 98. Tu invitación caduca el{{ date(+2days)|date }}
  • 99. Tu invitación caduca el{{ date(+2days)|date }}{% if date(fechaNacimiento) < date(-18years) %} ¡Eres menor de edad!{% endif %}
  • 100. La última sorpresa de#deSymfony se desvelará el{{ date(next Monday)|date() }}
  • 101. OPERADORES PROPIOS1.* BÁSICO INTERMEDIO AVANZADO
  • 102. $loader = new Twig_Loader_Filesystem(...);$twig = new Twig_Environment($loader, array(...));$twig->addExtension(new OperatorsExtension());
  • 103. Operador "quédate con el mayor" {{ 5 >> 2 }} 5 {{ 4 >> 20 }} 20
  • 104. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(), array(>> => array( precedence => 20, class => DesymfonyOperatorsMaxOperator, associativity => Twig_ExpressionParser::OPERATOR_LEFT ) )); }}
  • 105. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(), array(>> => array( precedence => 20, class => DesymfonyOperatorsMaxOperator, associativity => Twig_ExpressionParser::OPERATOR_LEFT ) )); }}
  • 106. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(), array(>> => array( precedence => 20, class => DesymfonyOperatorsMaxOperator, associativity => Twig_ExpressionParser::OPERATOR_LEFT ) )); }}
  • 107. 2 +3**2 / 4 .. 4-5//2 Operador Precedence != 20 + 30 ** 200
  • 108. {{ a >> b }} max($a, $b); TWIG PHP
  • 109. class MaxOperator extends Twig_Node_Expression_Binary{ public function compile(Twig_Compiler $compiler) { $compiler ->raw(max() ->subcompile($this->getNode(left)) ->raw(, ) ->subcompile($this->getNode(right)) ->raw()) ; }
  • 110. class MaxOperator extends Twig_Node_Expression_Binary{ public function compile(Twig_Compiler $compiler) { $compiler ->raw(max() ->subcompile($this->getNode(left)) ->raw(, ) ->subcompile($this->getNode(right)) ->raw()) ; } max($a, $b);
  • 111. // line 23echo twig_escape_filter($this->env, max(5, 2), "html", null, true);
  • 112. $compiler ->raw() (literal) ->write() (indentado) ->string() (entrecomillado) ->indent() (indentar) ->outdent() (desindentar);
  • 113. Operador "cambia claves por valores" PHP array_flip(range(a, z))TWIG {% for i in <->(a..z) %} {{ i }}, {% endfor %}
  • 114. Operador "cambia claves por valores" PHP array_flip(range(a, z))TWIG {% for i in <->(a..z) %} {{ i }}, {% endfor %}
  • 115. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(<-> => array( precedence => 50, class => DesymfonyOperatorsFlipOperator, ), array() )); }}
  • 116. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(<-> => array( precedence => 50, class => DesymfonyOperatorsFlipOperator, ), array() )); }}
  • 117. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(<-> => array( precedence => 50, class => DesymfonyOperatorsFlipOperator, ), array() )); }}
  • 118. namespace DesymfonyOperators;class FlipOperator extends Twig_Node_Expression_Unary{ public function compile(Twig_Compiler $compiler) { $compiler ->raw("array_flip(") ->subcompile($this->getNode(node)) ->raw(")") ; }
  • 119. namespace DesymfonyOperators;class FlipOperator extends Twig_Node_Expression_Unary{ public function compile(Twig_Compiler $compiler) { $compiler ->raw("array_flip(") ->subcompile($this->getNode(node)) ->raw(")") ; } array_flip($coleccion);
  • 120. // line 17$context[_parent] = (array) $context;$context[_seq] = twig_ensure_traversable(array_flip(range("a", "z")));foreach ($context[_seq] as $context["_key"] => $context["i"]) { // line 18 echo " "; if (isset($context["i"])) { $_i_ = $context["i"]; } else { $_i_ = null; } echo twig_escape_filter($this->env, $_i_, "html", null, true); echo ",";}
  • 121. // line 17$context[_parent] = (array) $context;$context[_seq] = twig_ensure_traversable(array_flip(range("a", "z")));foreach ($context[_seq] as $context["_key"] => $context["i"]) { // line 18 echo " "; if (isset($context["i"])) { $_i_ = $context["i"]; } else { $_i_ = null; } echo twig_escape_filter($this->env, $_i_, "html", null, true); echo ",";}
  • 122. SUPER CACHÉ1.* BÁSICO INTERMEDIO AVANZADO
  • 123. # mkfs -q /dev/ram1 65536# mkdir -p /twigcache# mount /dev/ram1 /twigcacheInspirado por: http://www.cyberciti.biz/faq/howto!create!linux!ram!disk!filesystem/
  • 124. $twig = new Twig_Environment( $loader, array(cache => /twigcache));# app/config/config.ymltwig: cache: /twigcache
  • 125. ETIQUETAS PROPIAS1.* BÁSICO INTERMEDIO AVANZADO
  • 126. etiquetasoperadores #1 tests #2 #3
  • 127. {% source simple.twig %}{% source ../../../composer.json %}
  • 128. 1. Clase Token Parser TWIG TWIG2. Clase Node TWIG PHP
  • 129. $loader = new Twig_Loader_Filesystem(...);$twig = new Twig_Environment($loader, array(...));$twig->addTokenParser(new SourceTokenParser());
  • 130. {% source ... %}class SourceTokenParser extends Twig_TokenParser{ public function getTag() { return source; }}
  • 131. namespace DesymfonyTags;use DesymfonyTagsSourceNode;class SourceTokenParser extends Twig_TokenParser{ public function parse(Twig_Token $token) { $lineno = $token->getLine(); $value = $this->parser->getExpressionParser()->parseExpression(); $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); return new SourceNode($value, $lineno, $this->getTag()); }}
  • 132. class SourceNode extends Twig_Node{ public function __construct(Twig_Node_Expression $value, $lineno, $tag = null) { parent::__construct(array(file => $value), array(), $lineno, $tag); } public function compile(Twig_Compiler $compiler) { $compiler -> // ... ->write(echo file_get_contents() ->subcompile($this->getNode(file)) ->raw();); ; }}
  • 133. // line 3echo file_get_contents("simple.twig");// line 4echo "n";// line 5echo file_get_contents("../../../composer.json");// line 6echo "n";
  • 134. INTERPOLACIÓN1.5 BÁSICO INTERMEDIO AVANZADO
  • 135. La oferta cuesta 25.78 euros(30.42 con IVA) y es válidahasta el 10/06/2012
  • 136. La oferta cuesta 25.78 euros(30.42 con IVA) y es válidahasta el 10/06/2012
  • 137. La oferta cuesta 25.78 euros (30.42 con IVA) y esválida hasta el 10/06/2012 ~{{ La oferta cuesta ~ oferta.precio ~ euros ( ~oferta.precio*1.18 ~ con IVA) y es válida hasta el ~oferta.fechaExpiracion|date() }}
  • 138. La oferta cuesta 25.78 euros (30.42 con IVA) y esválida hasta el 10/06/2012 format(){{ La oferta cuesta %.2f euros (%.2f con IVA) y esválida hasta el %s|format(oferta.precio,oferta.precio*1.18, oferta.fechaExpiracion|date()) }}
  • 139. La oferta cuesta 25.78 euros (30.42 con IVA) y esválida hasta el 10/06/2012 replace(){{ La oferta cuesta :precio euros (:total con IVA) y esválida hasta el :fecha|replace({ :precio:oferta.precio, :total: oferta.precio*1.18, :fecha:oferta.fechaExpiracion|date() }) }}
  • 140. La oferta cuesta 25.78 euros (30.42 con IVA) y esválida hasta el 10/06/2012{{ "La oferta cuesta #{oferta.precio}euros (#{oferta.precio*1.18} con IVA)y es válida hasta el#{oferta.fechaExpiracion|date()}" }}
  • 141. {{ "... #{ expresión } ..." }}
  • 142. {{ "... #{ expresión } ..." }}
  • 143. NUEVOS FILTROS Y ETIQUETAS1.5 BÁSICO INTERMEDIO AVANZADO
  • 144. {% flush %}
  • 145. {% do %}
  • 146. {{ 1 + 1 }} 2{% do 1 + 1 %} (nada)
  • 147. {% set lista = [a, b, c, d] %}{{ lista|shift }}{% do lista|shift %}Fuente: https://github.com/fabpot/Twig/issues/446
  • 148. [:]
  • 149. {% set lista = [a, b, c, d] %} {{ lista[1:] }}
  • 150. {% set lista = [a, b, c, d] %} {{ lista[-1:] }}
  • 151. {% set lista = [a, b, c, d] %} {{ lista[2:2] }}
  • 152. {{ @username[1:] }}{{ Lorem ipsum...[-4:10] }}
  • 153. operadores bitwise{{ a b-and b }} $a ^ $b{{ a b-xor b }} $a << $b{{ a b-or b }} $a >> $b TWIG PHP
  • 154. TWIG_TEMPLATE1.* BÁSICO INTERMEDIO AVANZADO
  • 155. <html> <head> ... </head> <body> ... <span data-host="Darwin mbp.local 10.8.0 Darwin Kernel Version10.8.0: Tue Jun 7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386" data-elapsed="0.97804594039917 sec."data-timestamp="1339609672.9781"></span> </body></html>
  • 156. app/cache/dev/twig/
  • 157. app/cache/dev/twig/
  • 158. app/cache/dev/twig/09/fc/2d8a188dda8245d295e6324582f2.php<?php/* ::frontend.html.twig */class __TwigTemplate_09fc2d8a188dda8245d295e6324582f2extends Twig_Template{ public function __construct(Twig_Environment $env) { parent::__construct($env); $this->parent = $this->env->loadTemplate("::base.html.twig"); $this->blocks = array( stylesheets => array($this, block_stylesheets), javascripts => array($this, block_javascripts), body => array($this, block_body), article => array($this, block_article),
  • 159. class __TwigTemplate_09f...2f2 extends Twig_Template{ // ...}
  • 160. namespace CuponBackendBundleController;use SymfonyBundleFrameworkBundleControllerController;class UsuarioController extends Controller{ public function indexAction() { //... return $this->render( BackendBundle:Usuario:index.html.twig, array( ... ) ); }}
  • 161. Symfony/Bundle/FrameworkBundle/Controller/Controller.phpfunction render($view, $parameters, $response) { return $this->container->get(templating) ->renderResponse($view, $parameters, $response);}
  • 162. lib/Twig/Environment.phppublic function render($name, array $context = array()){ return $this->loadTemplate($name) ->render($context);}
  • 163. return $this->render( ... );render( ... ) Twig_Template
  • 164. return $this->render( ... );render( ... ) Twig_Template
  • 165. <html> <head> ... </head> <body> ... <span data-host="Darwin mbp.local 10.8.0 Darwin Kernel Version10.8.0: Tue Jun 7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386" data-elapsed="0.97804594039917 sec."data-timestamp="1339609672.9781"></span> </body></html>
  • 166. base_template_class$loader = new Twig_Loader_Filesystem(__DIR__./../Resources/views);$twig = new Twig_Environment($loader, array( base_template_class => DesymfonyTemplateMiTwigTemplate,));# app/config/config.ymltwig: base_template_class: "DesymfonyTemplateMiTwigTemplate"
  • 167. namespace DesymfonyTemplate;abstract class MiTwigTemplate extends Twig_Template{ public function render(array $context) { $traza = sprintf(<span data-host="%s" data-elapsed="%s sec." data-timestamp="%s"></span>, php_uname(), microtime(true)-$_SERVER[REQUEST_TIME], microtime(true) ); return str_replace(</body>, $traza."n</body>", parent::render($context) ); }}
  • 168. TWIG LINTER1.* BÁSICO INTERMEDIO AVANZADO
  • 169. $twig = new Twig_Environment($loader, array(..));try { $twig->parse($twig->tokenize($plantilla)); echo "[OK] La sintaxis de la plantilla es correcta";} catch (Twig_Error_Syntax $e) { echo "[ERROR] La plantilla tiene errores de sintaxis";}
  • 170. $ php app/console twig:lint @MyBundle$ php app/console twig:lint src/Cupon/OfertaBundle/Resources/views/index.html.twig
  • 171. twig:lint
  • 172. twig:lintSYMFONY 2.1
  • 173. twig:lint SYMFONY 2.1DESYMFONY 2013
  • 174. ¡muchas gracias!
  • 175. Contacto • javier.eguiluz@gmail.com • github.com/javiereguiluz • twitter.com/javiereguiluz • linkd.in/javiereguiluz