Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Twig avanzado (sf2Vigo)

16,946 views

Published on

Buenas prácticas, trucos, snipets y buenos usos del sistema de plantillas Twig, tanto dentro de Symfony2 como en proyectos PHP independientes

Published in: Technology

Twig avanzado (sf2Vigo)

  1. 1. Twig avanzadoJavier Eguiluz Jornadas Symfony2 Galicia 25-26 noviembre 2011 #sf2Vigo
  2. 2. me presento • Javier Eguiluz • formador en Symfony2 y nuevas tecnologías
  3. 3. creador de http://symfony.es
  4. 4. apasionado de Symfony http://connect.sensiolabs.com/ profile/javier.eguiluz
  5. 5. objetivos de la sesión • Buenas prácticas • Trucos • Usos avanzados • Snipets
  6. 6. Si no sabes Twig, te vas a perder a partir de la siguiente transparencia
  7. 7. Aprende Twigen 5 minutos
  8. 8. «Twig es un lenguaje ymotor de plantillas PHP»
  9. 9. twig se puede usar en CualquierSymfony2 proyecto PHP
  10. 10. ¿Por qué usar Twig?
  11. 11. $usuariopublic function getNombre(){ return $this->nombre;}
  12. 12. TWIG{{ usuario.nombre }}
  13. 13. PHPecho $usuario->getNombre()
  14. 14. PHP<?phpecho $usuario->getNombre();?>
  15. 15. PHP<?phpecho htmlspecialchars( $usuario->getNombre(), ENT_QUOTES, UTF-8);?>
  16. 16. TWIG {{ usuario.nombre }} PHP<?php echo htmlspecialchars($usuario->getNombre(), ENT_QUOTES, UTF-8); ?>
  17. 17. Mostrarinformación
  18. 18. {# ... #}{% ... %}{{ ... }}
  19. 19. <p> Hola {{ usuario }}Tienes {{ edad }} años yvives en {{ ciudad }} </p>
  20. 20. <p> Hola {{ usuario.nombre }}Tienes {{ usuario.edad }}años y vives en{{ usuario.ciudad }} </p>
  21. 21. {{ usuario.nombre }}
  22. 22. {{ usuario.nombre }}1. $usuario["nombre"]2. $usuario->nombre3. $usuario->nombre()4. $usuario->getNombre()5. $usuario->isNombre()6. null
  23. 23. <?php Template.phpabstract class Twig_Template implements Twig_TemplateInterface{ // ... protected function getAttribute( $object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false) { // ...
  24. 24. twig-extDerick Rethans
  25. 25. http://github.com/derickr/twig-ext
  26. 26. Modificarinformación
  27. 27. {{ descripcion }}
  28. 28. {{ descripcion | striptags }}
  29. 29. {{ titular | striptags | upper }}
  30. 30. <strong>Lorem ipsum</strong>dolor sit <em>amet</em>
  31. 31. {{ biografia }}
  32. 32. &lt;strong&gt;Loremipsum&lt;/strong&gt; dolorsit &lt;em&gt;amet&lt;/em&gt;
  33. 33. {{ biografia | raw }}
  34. 34. Espaciosen blanco
  35. 35. <ul> <li> <a ... >XXX</a> </li> <li> ...
  36. 36. {% spaceless %}
  37. 37. {% spaceless %}<ul> <li> <a ... >XXX</a> </li> <li> ...{% endspaceless %}
  38. 38. <ul><li><a ... >XXX</a></li><li>...
  39. 39. Estructuras de control
  40. 40. {% for elemento in coleccion %} {# ... #}{% endfor %}
  41. 41. {% for clave, elemento in coleccion %} {# ... #}{% endfor %}
  42. 42. {% if condicion1 %} {# ... #}{% elseif condicion2 %} {# ... #}{% else %} {# ... #}{% endif %}
  43. 43. Herenciade plantillas
  44. 44. PORTADA
  45. 45. CONTACTO
  46. 46. # TITULO # # LATERAL # # CONTENIDOS #
  47. 47. # TITULO # layout.twig # LATERAL # # CONTENIDOS #
  48. 48. <html> <head> ... </head> layout.twig<body> <h1> {% block titulo %}{% endblock %} </h1> {% block contenidos %}{% endblock %} {% block lateral %}{% endblock %}</body></html>
  49. 49. <html> <head> ... </head> portada.twig<body> <h1> PORTADA </h1> <div id="contenidos">...</div> <div id="lateral">...</div></body></html>
  50. 50. <html> <head> ... </head> portada.twig<body> <h1> PORTADA </h1> <div id="contenidos">...</div> <div id="lateral">...</div></body></html>
  51. 51. portada.twig PORTADA<div id="contenidos">...</div><div id="lateral">...</div>
  52. 52. portada.twig{% extends "layout.twig" %} PORTADA <div id="contenidos">...</div> <div id="lateral">...</div>
  53. 53. {% extends "layout.twig" %} portada.twig{% block titulo %} PORTADA{% endblock %}{% block contenidos %} <div id="contenidos">...</div>{% endblock %}{% block lateral %} <div id="lateral">...</div>{% endblock %}
  54. 54. {% extends "layout.twig" %} contacto.twig{% block titulo %} CONTACTO{% endblock %}{% block contenidos %} <form>...</form>{% endblock %}{% block lateral %} <p>...</p>{% endblock %}
  55. 55. ya pasaron los5 minutos
  56. 56. DESARROLLOWEB ÁGIL CON todos los ejemplos que se muestranSYMFONY2 a continuación pertenecen al libro Desarrollo web ágil con Symfony2 (disponible próximamente) Javier Eguiluz
  57. 57. variables globales
  58. 58. # app/config/config.ymltwig: # ... globals: cp: 01001 iva: [1.04, 1.08, 1.18] version: 1.0.3
  59. 59. # app/config/config.ymltwig: # ... globals: cp: 01001 iva: [1.04, 1.08, 1.18] version: 1.0.3Precio {{ oferta.precio * iva[0] }}Coste de envío a {{ usuario.cp | default(cp) }}<footer> &copy; now|date(Y) - v.{{ version }}</footer>
  60. 60. # app/config/config.ymltwig: # ... globals: global: cp: 01001 iva: [1.04, 1.08, 1.18] version: 1.0.3
  61. 61. # app/config/config.ymltwig: # ... globals: global: cp: 01001 iva: [1.04, 1.08, 1.18] version: 1.0.3Precio {{ oferta.precio * global.iva[0] }}Coste de envío a {{ oferta.cp | default(global.cp) }}<footer> &copy; now|date(Y) - v.{{ global.version }}</footer>
  62. 62. servicios como variables globalesnamespace CuponOfertaBundleUtil;class Util{ static public function getSlug($cadena) { // ... return $slug; }}
  63. 63. # app/config/config.ymlservices: # ... cupon.utilidades: class: CuponOfertaBundleUtilUtil
  64. 64. # app/config/config.ymltwig: # ... globals: utilidades: @cupon.utilidades
  65. 65. # app/config/config.ymltwig: # ... globals: utilidades: @cupon.utilidades
  66. 66. {{ utilidades.getSlug(Lorem ipsumdolor sit amet) }}
  67. 67. depurando variables
  68. 68. <?php var_dump($oferta); ?>{% debug oferta %}
  69. 69. # app/config/config.ymlservices: twig.extension.debug: class: Twig_Extensions_Extension_Debug tags: - { name: twig.extension }
  70. 70. for ... else
  71. 71. {% for articulo in articulos %} {{ articulo.titulo }} {# ... #}{% endfor %}
  72. 72. {% for articulo in articulos %} {{ articulo.titulo }} {# ... #}{% else %} No hay artículos{% endfor %}
  73. 73. for ... if
  74. 74. Itera sólamente por las ofertas baratas
  75. 75. {% for oferta in ofertas if oferta.precio < 10 %} {# ... #}{% endfor %}
  76. 76. 1.2{% for elemento in coleccion if condicion %} {# ... #}{% endfor %}
  77. 77. Itera sólamente por los amigos del usuario{% set usuarios = 1..30 %}{% set amigos = [12, 29, 34, 55, 67] %}
  78. 78. {% set usuarios = 1..30 %}{% set amigos = [12, 29, 34, 55, 67] %}{% for usuario in usuarios if usuario in amigos %} {# sólo 12 y 29 #}{% endfor %}
  79. 79. Operadoresde división
  80. 80. operación resultado{{ 12 / 7 }} 1.7142857142{{ 12 // 7 }} 1{{ 12 % 7 }} 5
  81. 81. creandovariables
  82. 82. {% set nombre = José García %}{% set edad = 27 %}{% set precio = 104.83 %}{% set conectado = false %}{% set tasaImpuestos = [4, 8, 18] %}
  83. 83. {% set perfil = { nombre: José García, perfiles: [usuario, admin], edad: 27, validado: true} %}
  84. 84. {% set nombreCompleto = nombre ~ ~ apellidos %}{% set experiencia = edad ~ años %}
  85. 85. {% set perfil %} Nombre: {{ usuario.nombre }} Apellidos: {{ usuario.apellidos }} Edad: {{ usuario.edad }} años Página: {{ usuario.url }}{% endset %}{{ perfil }}
  86. 86. {% set nombre, edad, activado = José, 27, false %}{{ nombre }}{{ edad }}{% if activado %}
  87. 87. espaciosen blanco
  88. 88. class DefaultController extends Controller{ {% if comentarios %} /** * Primera línea * Segunda línea */ {% endif %}
  89. 89. NOclass DefaultController extends Controller{ /** * Primera línea * Segunda línea */
  90. 90. SIclass DefaultController extends Controller{ /** * Primera línea * Segunda línea */
  91. 91. SIclass DefaultController extends Controller{ /** * Primera línea * Segunda línea */
  92. 92. class DefaultController extends Controller{ {% if comentarios %} /** * Primera línea * Segunda línea */ {% endif %}
  93. 93. class DefaultController extends Controller{ {% if comentarios %} /** * Primera línea * Segunda línea */ {% endif %}
  94. 94. class DefaultController extends Controller{{% if comentarios %} /** * Primera línea * Segunda línea */{% endif %}
  95. 95. SIclass DefaultController extends Controller{ /** * Primera línea * Segunda línea */
  96. 96. class DefaultController extends Controller{ {% if comentarios %} /** * Primera línea * Segunda línea */ {% endif %}
  97. 97. class DefaultController extends Controller{ {% if comentarios -%} /** * Primera línea * Segunda línea */ {%- endif %}
  98. 98. SIclass DefaultController extends Controller{ /** * Primera línea * Segunda línea */
  99. 99. {% if condicion -%} {# ... #}{%- endif %}
  100. 100. class DefaultController extends Controller{ {% if comentarios -%} /** * Comentario */ {%- else -%} /** * @Anotacion(...) */ {%- endif %}
  101. 101. formatearinformación
  102. 102. {{ %.0f|format(time * 1000) }} ms
  103. 103. {{ %.0f|format(time * 1000) }} ms
  104. 104. {{ %.0f|format(time * 1000) }} ms
  105. 105. {{ %.0f|format(time * 1000) }} ms{{ %0.2f|format(time * 1000) }} ms
  106. 106. macrospolimórficas
  107. 107. {# formulario.html.twig #}{% macro campo(nombre, tipo, valor) %} <input type="{{ tipo }}" name="{{ nombre }}" value="{{ valor }}" />{% endmacro %}
  108. 108. {% from formularios.html.twig import campo as campo %}
  109. 109. {% from formularios.html.twig import campo as campo %}<table> {{ campo(nombre, text, José) }} {{ campo(apellidos, text, García Pérez) }} {{ campo(telefono, text) }}</table>
  110. 110. {% from formularios.html.twig import campo as campo %}<table> {{ campo(nombre, text, José) }} {{ campo(apellidos, text, García Pérez) }} {{ campo(telefono, text) }}</table><ul> {{ campo(nombre, text, José) }} {{ campo(apellidos, text, García Pérez) }} {{ campo(telefono, text) }}</ul>
  111. 111. {# formulario.html.twig #}{% macro campo(nombre, tipo, valor) %} <input type="{{ tipo }}" name="{{ nombre }}" value="{{ valor }}" />{% endmacro %}
  112. 112. {# formulario.html.twig #}{% macro campo(nombre, tipo, valor) %} <input type="{{ tipo }}" name="{{ nombre }}" value="{{ valor }}" />{% endmacro %}{% macro fila(nombre, tipo, valor) %} <tr> <td>{{ nombre | capitalize }}</td> <td>{{ _self.campo(nombre, tipo, valor) }}</td> </tr>{% endmacro %}
  113. 113. {# formulario.html.twig #}{% macro campo(nombre, tipo, valor) %} <input type="{{ tipo }}" name="{{ nombre }}" value="{{ valor }}" />{% endmacro %}
  114. 114. {# formulario.html.twig #}{% macro campo(nombre, tipo, valor) %} <input type="{{ tipo }}" name="{{ nombre }}" value="{{ valor }}" />{% endmacro %}{% macro item(nombre, tipo, valor) %} <li> {{ _self.campo(nombre, tipo, valor) }} </li>{% endmacro %}
  115. 115. {% from formularios.html.twig import campo as campo %} {{ campo(nombre, text, José) }} {{ campo(apellidos, text, García Pérez) }} {{ campo(telefono, text) }}
  116. 116. {% from formularios.html.twig import fila as campo %}<table> {{ campo(nombre, text, José) }} {{ campo(apellidos, text, García Pérez) }} {{ campo(telefono, text) }}</table>
  117. 117. {% from formularios.html.twig import item as campo %}<ul> {{ campo(nombre, text, José) }} {{ campo(apellidos, text, García Pérez) }} {{ campo(telefono, text) }}</ul>
  118. 118. filtros dependientes del entorno
  119. 119. public function getFilters(){ return array(longitud => new Twig_Filter_Method($this, longitud) );}function longitud($valor){ return strlen($valor);}
  120. 120. public function getFilters(){ return array(longitud => new Twig_Filter_Method($this, longitud) );}function longitud($valor){ return strlen($valor);}
  121. 121. function longitud($valor){ return mb_strlen($valor, EUC-JP);}
  122. 122. public function getFilters(){ return array( longitud => new Twig_Filter_Method( $this, longitud, array(needs_environment => true) ) );}
  123. 123. public function getFilters(){ return array( longitud => new Twig_Filter_Method( $this, longitud, array(needs_environment => true) ) );}
  124. 124. function longitud(Twig_Environment $entorno, $valor){ $codificacion = $entorno->getCharset(); return mb_strlen($valor, $codificacion);}
  125. 125. class Twig_Environment{ const VERSION = 1.1.2; // ... $options = array_merge(array( debug => false, charset => UTF-8, base_template_class => Twig_Template, strict_variables => false, autoescape => true, cache => false, auto_reload => null, optimizations => -1, ), $options); // ...}
  126. 126. notación bundle
  127. 127. {% includeMiBundle:Carpeta:plantilla.html.twig %}
  128. 128. {% includeMiBundle:Carpeta:plantilla.html.twig %} src/MiAplicacion/ MiBundle/ Resources/ views/ Carpeta/ plantilla.html.twig
  129. 129. {% includeMiBundle:Carpeta:plantilla.html.twig %}
  130. 130. {% includeMiBundle:Carpeta:plantilla.html.twig %}{% include MiBundle:Carpeta:Subcarpeta/ plantilla.html.twig %}
  131. 131. {% includeMiBundle:Carpeta:plantilla.html.twig %}{% include MiBundle:Carpeta:Subcarpeta/ plantilla.html.twig %}{% include MiBundle:Carpeta:Subcarpeta1/ Subcarpeta2/plantilla.html.twig %}
  132. 132. {% includeMiBundle:Carpeta:plantilla.html.twig %}
  133. 133. {% includeMiBundle:Carpeta:plantilla.html.twig %}{% includeMiBundle::Carpeta/plantilla.html.twig %}
  134. 134. {% includeMiBundle:Carpeta:plantilla.html.twig %}
  135. 135. {% includeMiBundle:Carpeta:plantilla.html.twig %}{% includeviews/Carpeta/plantilla.html.twig %}
  136. 136. opciones deconfiguración
  137. 137. # app/config/config.ymltwig: autoescape: true auto_reload: ~ cache: %kernel.cache_dir%/twig charset: %kernel.charset% debug: %kernel.debug% strict_variables: ~
  138. 138. $twig = new Twig_Environment($loader, array( debug => true, strict_variables => true, charset => UTF-8, cache => __DIR__./cache));
  139. 139. # app/config/config.yml twig: base_template_class: Twig_Template<?phpclass __TwigTemplate_82262eae3f96052ef64432a9ddc53915 extends Twig_Template{ protected $parent; public function __construct(Twig_Environment $env) { // ... }
  140. 140. # app/config/config.yml twig: base_template_class: Twig_Template<?phpclass __TwigTemplate_82262eae3f96052ef64432a9ddc53915 extends Twig_Template{ protected $parent; public function __construct(Twig_Environment $env) { // ... }
  141. 141. # app/config/config.ymltwig: # ... exception_controller: SymfonyBundleTwigBundleControllerExceptionController::showAction
  142. 142. # app/config/config.ymltwig: # ... form: resources: [ ... ]
  143. 143. formulariospersonalizados
  144. 144. modificar campos de una plantilla{{ form_row(noticia.url) }}
  145. 145. modificar campos de una plantilla{{ form_row(noticia.url) }}Label
  146. 146. modificar campos de una plantilla{{ form_row(noticia.url) }}Label{% block url_widget %}{% spaceless %} {% set type = type|default(url) %} {{ block(field_widget) }}{% endspaceless %}{% endblock url_widget %}
  147. 147. {{ form_row(noticia.url) }}{% form_theme form _self %}{% block url_widget %} {% set type = url %} <em>http://</em> {{ block(field_widget) }}{% endblock url_widget %}
  148. 148. {{ form_row(noticia.url) }}{% form_theme form _self %}{% block url_widget %} {% set type = url %} <em>http://</em> {{ block(field_widget) }}{% endblock url_widget %}
  149. 149. {{ form_row(noticia.url) }}{% form_theme form _self %}{% block url_widget %} {% set type = url %} <em>http://</em> {{ block(field_widget) }}{% endblock url_widget %}Label http://
  150. 150. modificar campos de varias plantillas{# src/.../Resources/views/Form/form.html.twig #}{% block url_widget %} {% set type = url %} <em>http://</em> {{ block(field_widget) }}{% endblock url_widget %}
  151. 151. {% form_theme form MiBundle:Form:form.html.twig %}{{ form_row(noticia.titular) }}{{ form_row(noticia.publicada) }}{{ form_row(noticia.url) }}
  152. 152. modificar todos los formularios# app/config/config.ymltwig: # ... form: resources: - form_div_layout.html.twig
  153. 153. # app/config/config.ymltwig: # ... form: resources: - form_table_layout.html.twig
  154. 154. {% use "form_div_layout.html.twig" %}{% block field_row %}{% spaceless %} <tr> <td> {{ form_label(form, label|default(null)) }} </td> <td> {{ form_errors(form) }} {{ form_widget(form) }} </td> </tr>{% endspaceless %}{% endblock field_row %}{# ... #}
  155. 155. {% use "form_div_layout.html.twig" %}{% block field_row %} {# ... #}{% endblock %}{% block form_errors %} {# ... #}{% endblock %}{% block hidden_row %} {# ... #}{% endblock %}{% block form_widget %} {# ... #}{% endblock %}
  156. 156. # app/config/config.ymltwig: # ... form: resources: - MiBundle:Form:form.html.twig
  157. 157. mostrandocampos de fecha
  158. 158. {{ form_row(fecha) }}
  159. 159. {{ form_label(fecha) }}{{ form_errors(fecha) }}{{ form_widget(fecha) }}
  160. 160. {{ form_label(fecha) }}{{ form_errors(fecha) }}{{ form_widget(fecha.year) }}{{ form_widget(fecha.month) }}{{ form_widget(fecha.day) }}
  161. 161. generando código
  162. 162. «Twig genera confacilidad cualquier tipo de contenido»
  163. 163. public function indexAction() Symfony2{ $em = $this->getDoctrine()->getEntityManager(); $entities = $em->getRepository({{ bundle }}:{{ entity }}) ->findAll();{% if annotation == format %} return array(entities => $entities);{% else %} return $this->render({{ bundle }}: {{ entity|replace({: /}) }}:index.html.twig, array(entities => $entities));{% endif %}}
  164. 164. easybook3/* page size, margins, headers & footers--------------------------------------------- */@page { size: {{ edition.page_size }};}{% if edition.two_sided %}@page:right { margin: {{ edition.margin.top|default(25mm) }}{{ edition.margin.outter|default(20mm) }}{{ edition.margin.bottom|default(25mm) }}{{ edition.margin.inner|default(30mm) }}; @top-left { /* ... */ }
  165. 165. {% block NamespaceDeclaration %}{% if namespace %} Doctrine2namespace {{ namespace }}; ActiveRecorduse {{ namespace }}Base{{ classname }} as Base{{ classname }};{% else %}use Base{{ classname }} as Base{{ classname }};{% endif %}{% endblock %}{% block DocBlock %}/** * ActiveRecord class. */{% endblock %}{% block ClassDeclaration %}class {{ classname }} extends Base{{ classname }}{% endblock %}{{% block Body %} // add your code here{% endblock %}}
  166. 166. https://github.com/cedriclombardot/TwigGenerator
  167. 167. twig.js
  168. 168. <select id="ciudad"> {% for ciudad in ciudades %} <option value="{{ ciudad.slug }}"> {{ ciudad.nombre }} </option> {% endfor %}</select>
  169. 169. <script type="text/javascript"> var lista = document.getElementById(ciudad); var ciudad = lista.options[lista.selectedIndex].value; lista.onchange = function() { var url = {{ path(portada, {ciudad: ciudad }) }}; window.location = url; };</script>
  170. 170. <script type="text/javascript"> var lista = document.getElementById(ciudad); var ciudad = lista.options[lista.selectedIndex].value; lista.onchange = function() { var url = {{ path(portada, {ciudad: ciudad }) }}; window.location = url; };</script>
  171. 171. <script type="text/javascript"> var lista = document.getElementById(ciudad); var ciudad = lista.options[lista.selectedIndex].value; lista.onchange = function() { var url = Routing.generate(portada, {ciudad: ciudad}); window.location = url; };</script>
  172. 172. <script type="text/javascript" src="{{ asset(bundles/fosjsrouting/js/router.js) }}"></script><script type="text/javascript" src="{{ path(fos_js_routing_js, {"callback":"fos.Router.setData"}) }}"></script><script type="text/javascript"> var lista = document.getElementById(ciudad); var ciudad = lista.options[lista.selectedIndex].value; lista.onchange = function() { var url = Routing.generate(portada, {ciudad: ciudad}); window.location = url; };</script>
  173. 173. https://github.com/FriendsOfSymfony/FOSJsRoutingBundle
  174. 174. {% twig_js name="perfil" %}Nombre: {{ nombre }}Apellidos: {{ apellidos }}
  175. 175. {% twig_js name="perfil" %}Nombre: {{ nombre }}Apellidos: {{ apellidos }}
  176. 176. <script type="text/javascript" src="twig.js"></script><script type="text/javascript" src="perfil.js"></script><script type="text/javascript"> alert(Twig.render(perfil, { nombre: José, apellidos: Pérez }));</script>
  177. 177. https://github.com/schmittjoh/twig.js
  178. 178. flexible
  179. 179. {{ ... | length }}Tienes {{ amigos|length }} amigosy tu nombre tiene{{ nombre|length }} letras
  180. 180. {{ ... | length }} count( )Tienes {{ amigos|length }} amigosy tu nombre tiene{{ nombre|length }} letras
  181. 181. {{ ... | length }} count( )Tienes {{ amigos|length }} amigosy tu nombre tiene{{ nombre|length }} letras strlen( )
  182. 182. {{ ... in ... }}{% if fecha in [2005, 2006] %} Eres un early-adopter{% endif %}{% if password in login %} La contraseña no puede ser una parte del login{% endif %}
  183. 183. {{ ... in ... }} in_array( ){% if fecha in [2005, 2006] %} Eres un early-adopter{% endif %}{% if password in login %} La contraseña no puede ser una parte del login{% endif %}
  184. 184. {{ ... in ... }} in_array( ){% if fecha in [2005, 2006] %} Eres un early-adopter{% endif %} strpos( ){% if password in login %} La contraseña no puede ser una parte del login{% endif %}
  185. 185. {% for letra in a|upper..inicial|default(z)|upper %} {{ letra }}{% endfor %}
  186. 186. {% for letra in a|upper..inicial|default(z)|upper %} {{ letra }}{% endfor %}{% filter upper %}{% for letra in a..inicial|default(z) %} {{ letra }}{% endfor %}{% endfilter %}
  187. 187. {% for letra in a|upper..inicial|default(z)|upper %} {{ letra }}{% endfor %}{% filter upper %}{% for letra in a..inicial|default(z) %} {{ letra }}{% endfor %}{% endfilter %}{% for letra in a..inicial|default(z) %} {{ letra | upper }}{% endfor %}
  188. 188. propiedades variables
  189. 189. {{ objeto.propiedad }}
  190. 190. {{ objeto.propiedad }}
  191. 191. {% set bundles = { AsseticBundle => .../vendor/..., BackendBundle => .../src/..., CiudadBundle => .../src/..., DoctrineBundle => .../vendor/..., ...} %}
  192. 192. NO{{ bundles.AsseticBundle }}
  193. 193. SI{% set nombre = AsseticBundle %}{{ bundles[nombre] }}
  194. 194. {% for name in bundles|keys|sort %}<tr> <th>{{ name }}</th> <td>{{ bundles[name] }}</td></tr>{% endfor %}
  195. 195. {% set usuarios = [ { email: ..@.. }, { movil: 9.... }] %}
  196. 196. {% set usuarios = [ { email: ..@.. }, { movil: 9.... }] %}{% for usuario in usuarios %} {{ usuario.nombre }} Contacto {{ usuario.????? }}{% endfor %}
  197. 197. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %}
  198. 198. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %} {{ usuario.contacto }} resultado email
  199. 199. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %}
  200. 200. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %} {{ usuario[contacto] }} resultado ERROR
  201. 201. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %}
  202. 202. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %} {{ usuario[usuario.contacto] }} resultado ..@..
  203. 203. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %}
  204. 204. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %} {{ attribute(usuario, usuario.contacto) }}
  205. 205. {% set usuarios = [ { email: ..@.., contacto: email }, { movil: 9...., contacto: movil }] %} {{ attribute(usuario, usuario.contacto) }} resultado ..@..
  206. 206. 1.2{{ attribute(objeto, propiedad) }}{{ attribute(objeto, expresion) }}{{ attribute(producto, foto ~ i) }}
  207. 207. 1.2{{ attribute(objeto, metodo) }}{{ attribute(objeto, metodo, argumentos) }}
  208. 208. herenciadinámica
  209. 209. {% extends usuario.tipo ~ .html.twig %}{# usuario = {tipo: admin} #}admin.html.twig{# usuario = {tipo: usuario} #}usuario.html.twig
  210. 210. {% extends listado ? listado.html.twig : tabla.html.twig %}
  211. 211. 1.2{% extends [primera.html.twig, segunda.html.twig, tercera.html.twig] %}
  212. 212. {% extends noticia.html.twig %}
  213. 213. {% extends [categoria_ ~ noticia.categoria ~ .html.twig,seccion_ ~ noticia.seccion ~ .html.twig,noticia.html.twig] %}
  214. 214. includedinámico
  215. 215. 1.2{% include [primera.html.twig, segunda.html.twig, tercera.html.twig] %}
  216. 216. {% include [lateral_ ~ noticia.categoria ~ .html.twig,lateral_ ~ noticia.seccion ~ .html.twig,lateral.html.twig] %}
  217. 217. {% set seccion = ... %}{% include lateral_ ~ seccion ~ .html.twig%}
  218. 218. 1.2{% set seccion = ... %}{% include lateral_ ~ seccion ~ .html.twig ignore missing%}
  219. 219. {% include ... ignore missing %}{% include ... ignore missing with { ... } %}{% include ... ignore missing with { ... } only %}
  220. 220. muchasgracias
  221. 221. dudaspreguntascomentarios
  222. 222. contactajavier.eguiluz@gmail.comconectalinkedin.com/in/javiereguiluz
  223. 223. copyrightLos contenidos de estapresentación son propiedadde su autor. No se puedenreutilizar sin el consentimientoexpreso de su autor.

×