0
Twig, los mejores trucos ytécnicas avanzadasJavier EguíluzUniversitat Jaume I · Castellón · 15-16 junio 2012 · desymfony.com
¡muchas gracias a nuestros patrocinadores! PATROCINADOR   PLATINOPATROCINADORES         OROPATROCINADORES      PLATAPATROC...
Agenda • Buenas prácticas • Técnicas avanzadas • Trucos y   cosas nuevas
CódigoEl código fuente de los ejemplosmás avanzados de esta ponenciaestá disponible en:https://github.com/javiereguiluz/de...
PERSONALIZACIÓN          EXTREMA DE         FORMULARIOS1.*     BÁSICO INTERMEDIO AVANZADO
<div>  {{ form_label(form.nombre) }}  {{ form_errors(form.nombre) }}  {{ form_widget(form.nombre) }}</div>
{% extends ::base.html.twig %}{% form_theme form _self %}{% block integer_widget %}  <div class="integer_widget">     {% s...
{% extends ::base.html.twig %}{% form_theme form _self %}{% block integer_widget %}  <div class="integer_widget">     {% s...
{% extends ::base.html.twig %}{% form_theme form _self %}{% block integer_widget %}  <div class="integer_widget">     {% s...
{% form_theme form _self %}{% block _formulario_nombre_widget %}  <div class="especial"><strong>     {{ block(field_widget...
{% form_theme form _self %}{% block _formulario_nombre_widget %}  <div class="especial"><strong>     {{ block(field_widget...
class UsuarioType extends AbstractType{   public function buildForm(FormBuilder $builder, array $options)   {     $builder...
class UsuarioType extends AbstractType{   public function buildForm(FormBuilder $builder, array $options)   {     $builder...
<strong>Label</strong>: Valor
<strong>Label</strong>: Valor<strong>{{ form.nombreCampo.vars.label }}</strong>:{{ form. nombreCampo.vars.value }}
<strong>Label</strong>: Valor<strong>{{ form.nombreCampo.vars.label }}</strong>:{{ form. nombreCampo.vars.value }}
CONSTANTES1.*   BÁSICO INTERMEDIO AVANZADO
{{ constant() }}
{{ constant(SymfonyComponentHttpKernelKernel::VERSION) }}
{{ constant(SymfonyComponentHttpKernelKernel::VERSION) }}namespace SymfonyComponentHttpKernel;abstract class Kernel implem...
namespace SymfonyComponentHttpKernel;abstract class Kernel implements KernelInterface{  // ...    const VERSION        = 2...
REDEFINE LOS         FILTROS POR             DEFECTO1.*   BÁSICO INTERMEDIO AVANZADO
{{ array|sort }}
asort()     array_multisort()arsort()    natcasesort()krsort()    natsort()ksort()     rsort()rsort()     shuffle()shuffle...
¿Dónde se definenlos filtros, etiquetas  y tags de Twig?
lib/twig/Extesion/Core.phpclass Twig_Extension_Core extends Twig_Extension {   public function getTokenParsers() {     ret...
{{ array|sort }}/** * Sorts an array. * * @param array $array An array */function twig_sort_filter($array){   asort($array...
natcasesort()a0, A1, a2, a10, ...
class MiCoreExtension      extends Twig_Extension_Core {   // ...}
class MiCoreExtension extends Twig_Extension_Core {    public function getFilters() {      // ...    }}
class MiCoreExtension extends Twig_Extension_Core {    public function getFilters() {      return array_merge(         par...
$twig = new Twig_Environment($loader, array( ... ));$twig->addExtension(new MiCoreExtension());
class MiCoreExtension extends Twig_Extension_Core{   public function getFilters()   {     return array_merge(parent::getFi...
{{ array|sort }}function twig_sort_filter($array){  natcasesort($array);  return $array;}
TODO SON         EXPRESIONES1.5   BÁSICO INTERMEDIO AVANZADO
{% include seccion_ ~ oferta.categoria ~ .twig %}{% for i in (1+3)//2..2**(3-1) %}{% endfor %}
{% set ofertas = {  (oferta ~ oferta.id):           ...,  (3 ~ _ ~ oferta.nombre|length): ...,  (2**2+1):                 ...
{% set ofertas = {  (oferta ~ oferta.id):           ...,  (3 ~ _ ~ oferta.nombre|length): ...,  (2**2+1):                 ...
{% set ofertas = {  oferta7040: ...,  3_57: ...,  5: ...} %}
EMBED1.8   BÁSICO INTERMEDIO AVANZADO
{% include %}   {% extends %}       {% embed %}
{% include ... %}
{% extends ... %}
{% embed ... %}
{% embed "lateral.twig" %}  {% block principal %}    ...  {% endblock %}{% endembed %}
{% embed "lateral.twig" %}  {% block secundario %}    ...  {% endblock %}{% endembed %}
{% include plantilla.twig %}{% embed plantilla.twig %}{% endembed %}
ESCAPING          AUTOMÁTICO1.8   BÁSICO INTERMEDIO AVANZADO
{% filter escape(js) %}  <script type="text/javascript">     var texto = "<p>Lorem ipsum dolor sit amet</p>";     alert(te...
x3cscript typex3dx22textx2fjavascriptx22x3ex0avar texto x3d x22x3cpx3eLorem ipsum dolor sit ametx3cx2fpx3ex22x3bx0a alertx...
{{ variable|e }}{{ variable|e(html) }}{{ variable|escape(js) }}{{ variable|e(js) }}{% autoescape %} ........... {% endauto...
$twig = new Twig_Environment($loader, array(    autoescape => function($nombre_plantilla) {      return decide_escape($nom...
$twig = new Twig_Environment($loader, array(    autoescape => function($nombre_plantilla) {      return decide_escape($nom...
RANDOM1.6   BÁSICO INTERMEDIO AVANZADO
{{ random() }}
{{ random() }}{{ random(10) }}
{{ random() }}{{ random(10) }}{{ random("abcde") }}
{{ random() }}{{ random(10) }}{{ random("abcde") }}{{ random([a, b, c]) }}
FUNCIONES             DINÁMICAS1.5   BÁSICO INTERMEDIO AVANZADO
the_ID()the_title()the_time()the_content()the_category()the_shortlink()
the_ID()the_title()the_time()the_content()the_category()the_shortlink()
the_ID()the_title()the_time()the_content()the_category()the_shortlink()the_*()
$twig->addFunction(     the_*,     new Twig_Function_Function(wordpress));function wordpress($funcion, $opciones){  // ...}
$twig->addFunction(     the_*,     new Twig_Function_Function(wordpress));function wordpress($funcion, $opciones){  // ...}
{{ the_ID() }}
{{ the_ID() }}function wordpress(ID, array()) { ... }
{{ the_ID() }}function wordpress(ID, array()) { ... }{{ the_content() }}
{{ the_ID() }}function wordpress(ID, array()) { ... }{{ the_content() }}function wordpress(content, array()){ ... }
{{ the_title(<h3>, </h3>) }}function wordpress(title, array(   <h3>, </h3>)) { ... }
*_*_link()next_image_link()next_post_link()next_posts_link()previous_image_link()previous_post_link()previous_posts_link()
php_*()
FILTROS             DINÁMICOS1.5   BÁSICO INTERMEDIO AVANZADO
{{ now|fecha_corta }}{{ now|fecha_larga }}fecha_*()
$twig->addFilter(     fecha_*,     new Twig_Filter_Function(fecha));function fecha($funcion, $opciones){  // ...}
VARIABLES              GLOBALES1.*   BÁSICO INTERMEDIO AVANZADO
{{ app.security }}{{ app.user }}{{ app.request }}{{ app.session }}{{ app.environment }}{{ app.debug }}
{{ _charset }}{{ _context }}{{ _self }}
{{ _charset }}   UTF-8
{{ _context }}{% for i in _context|keys %}  {{ i }}{% endfor %}
{{ _context }}{% for i in _context|keys %}  {{ i }}              app                      assetic{% endfor %}          _pa...
{{ _context }}{% for i in _context|keys %}  {{ i }}              app                      assetic{% endfor %}          _pa...
{{ _context }}{{ variable|mi_filtro(_context) }}
{{ _context }}{{ variable|mi_filtro(_context) }}                 SÓLO SI NO HAY                 OTRO REMEDIO
{{ _self }}Twig_Template
{{ _self }}{{ _self.getTemplateName }}OfertaBundle:Default:includes/oferta.html.twig
{{ _self }}{{ _self.blocks|keys|join(", ") }}title, stylesheets, rss, javascripts,id, body
{{ _self }}{{ _self.blocks|keys|join(", ") }}title, stylesheets, rss, javascripts,id, body                    SÓLO SI NO H...
EL SANDBOX1.*   BÁSICO INTERMEDIO AVANZADO
DEMO
DATE1.6   BÁSICO INTERMEDIO AVANZADO
{{ now|date("d/m/Y H:i:s") }}{{ now|date("d/m/Y H:i:s",              "America/Argentina/Buenos_Aires") }}{{ now|date("d/m/...
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ú...
$twig = new Twig_Environment($loader);$twig->getExtension(core)     ->setDateFormat(d-m-Y H:i:s, %d días);$twig->getExtens...
date()
{{ date() }}
{{ date() }}{{ date()|date() }}
{{ date() }}{{ date()|date() }}{{ date()|date("d/m/Y") }}
Tu invitación caduca el{{ date(+2days)|date }}
Tu invitación caduca el{{ date(+2days)|date }}{% if date(fechaNacimiento) < date(-18years) %}  ¡Eres menor de edad!{% endi...
La última sorpresa de#deSymfony se desvelará el{{ date(next Monday)|date() }}
OPERADORES             PROPIOS1.*   BÁSICO INTERMEDIO AVANZADO
$loader = new Twig_Loader_Filesystem(...);$twig = new Twig_Environment($loader, array(...));$twig->addExtension(new Operat...
Operador "quédate con el mayor"  {{ 5 >> 2 }}       5  {{ 4 >> 20 }}      20
class OperatorsExtension extends Twig_Extension{   public function getName() { return OperatorsExtension; }    public func...
class OperatorsExtension extends Twig_Extension{   public function getName() { return OperatorsExtension; }    public func...
class OperatorsExtension extends Twig_Extension{   public function getName() { return OperatorsExtension; }    public func...
2 +3**2 / 4 .. 4-5//2  Operador   Precedence    !=       20    +        30    **       200
{{ a >> b }}   max($a, $b);   TWIG            PHP
class MaxOperator extends Twig_Node_Expression_Binary{   public function compile(Twig_Compiler $compiler)   {     $compile...
class MaxOperator extends Twig_Node_Expression_Binary{   public function compile(Twig_Compiler $compiler)   {     $compile...
// line 23echo twig_escape_filter($this->env,     max(5, 2), "html", null, true);
$compiler  ->raw()       (literal)  ->write()     (indentado)  ->string()    (entrecomillado)  ->indent()    (indentar)  -...
Operador "cambia claves por valores" PHP    array_flip(range(a, z))TWIG    {% for i in <->(a..z) %}          {{ i }},     ...
Operador "cambia claves por valores" PHP    array_flip(range(a, z))TWIG    {% for i in <->(a..z) %}          {{ i }},     ...
class OperatorsExtension extends Twig_Extension{   public function getName() { return OperatorsExtension; }    public func...
class OperatorsExtension extends Twig_Extension{   public function getName() { return OperatorsExtension; }    public func...
class OperatorsExtension extends Twig_Extension{   public function getName() { return OperatorsExtension; }    public func...
namespace DesymfonyOperators;class FlipOperator extends Twig_Node_Expression_Unary{  public function compile(Twig_Compiler...
namespace DesymfonyOperators;class FlipOperator extends Twig_Node_Expression_Unary{  public function compile(Twig_Compiler...
// line 17$context[_parent] = (array) $context;$context[_seq] = twig_ensure_traversable(array_flip(range("a", "z")));forea...
// line 17$context[_parent] = (array) $context;$context[_seq] = twig_ensure_traversable(array_flip(range("a", "z")));forea...
SUPER CACHÉ1.*   BÁSICO INTERMEDIO AVANZADO
# mkfs -q /dev/ram1 65536# mkdir -p /twigcache# mount /dev/ram1 /twigcacheInspirado por: http://www.cyberciti.biz/faq/howt...
$twig = new Twig_Environment(   $loader,   array(cache => /twigcache));# app/config/config.ymltwig:  cache: /twigcache
ETIQUETAS                PROPIAS1.*   BÁSICO INTERMEDIO AVANZADO
etiquetasoperadores     #1                          tests   #2                    #3
{% source simple.twig %}{% source ../../../composer.json %}
1. Clase Token Parser   TWIG         TWIG2. Clase Node   TWIG         PHP
$loader = new Twig_Loader_Filesystem(...);$twig = new Twig_Environment($loader, array(...));$twig->addTokenParser(new Sour...
{% source ... %}class SourceTokenParser extends Twig_TokenParser{   public function getTag()   {     return source;   }}
namespace DesymfonyTags;use DesymfonyTagsSourceNode;class SourceTokenParser extends Twig_TokenParser{   public function pa...
class SourceNode extends Twig_Node{    public function __construct(Twig_Node_Expression $value, $lineno, $tag = null)    {...
// line 3echo file_get_contents("simple.twig");// line 4echo "n";// line 5echo file_get_contents("../../../composer.json")...
INTERPOLACIÓN1.5   BÁSICO INTERMEDIO AVANZADO
La oferta cuesta 25.78 euros(30.42 con IVA) y es válidahasta el 10/06/2012
La oferta cuesta 25.78 euros(30.42 con IVA) y es válidahasta el 10/06/2012
La oferta cuesta 25.78 euros (30.42 con IVA) y esválida hasta el 10/06/2012                           ~{{ La oferta cuesta...
La oferta cuesta 25.78 euros (30.42 con IVA) y esválida hasta el 10/06/2012                   format(){{ La oferta cuesta ...
La oferta cuesta 25.78 euros (30.42 con IVA) y esválida hasta el 10/06/2012                   replace(){{ La oferta cuesta...
La oferta cuesta 25.78 euros (30.42 con IVA) y esválida hasta el 10/06/2012{{ "La oferta cuesta #{oferta.precio}euros (#{o...
{{ "... #{ expresión } ..." }}
{{ "... #{ expresión } ..." }}
NUEVOS FILTROS Y            ETIQUETAS1.5     BÁSICO INTERMEDIO AVANZADO
{% flush %}
{% do %}
{{ 1 + 1 }}   2{% do 1 + 1 %}    (nada)
{% set lista = [a, b, c, d] %}{{ lista|shift }}{% do lista|shift %}Fuente: https://github.com/fabpot/Twig/issues/446
[:]
{% set lista = [a, b, c, d] %}          {{ lista[1:] }}
{% set lista = [a, b, c, d] %}         {{ lista[-1:] }}
{% set lista = [a, b, c, d] %}         {{ lista[2:2] }}
{{ @username[1:] }}{{ Lorem ipsum...[-4:10] }}
operadores bitwise{{ a b-and b }}   $a ^ $b{{ a b-xor b }}   $a << $b{{ a b-or b }}    $a >> $b    TWIG            PHP
TWIG_TEMPLATE1.*   BÁSICO INTERMEDIO AVANZADO
<html>  <head> ... </head>  <body>    ...    <span data-host="Darwin mbp.local 10.8.0 Darwin Kernel Version10.8.0: Tue Jun...
app/cache/dev/twig/
app/cache/dev/twig/
app/cache/dev/twig/09/fc/2d8a188dda8245d295e6324582f2.php<?php/* ::frontend.html.twig */class __TwigTemplate_09fc2d8a188dd...
class __TwigTemplate_09f...2f2      extends Twig_Template{   // ...}
namespace CuponBackendBundleController;use SymfonyBundleFrameworkBundleControllerController;class UsuarioController extend...
Symfony/Bundle/FrameworkBundle/Controller/Controller.phpfunction render($view, $parameters, $response) {    return $this->...
lib/Twig/Environment.phppublic function render($name, array $context = array()){  return $this->loadTemplate($name)       ...
return $this->render( ... );render( ... )      Twig_Template
return $this->render( ... );render( ... )      Twig_Template
<html>  <head> ... </head>  <body>    ...    <span data-host="Darwin mbp.local 10.8.0 Darwin Kernel Version10.8.0: Tue Jun...
base_template_class$loader = new Twig_Loader_Filesystem(__DIR__./../Resources/views);$twig = new Twig_Environment($loader,...
namespace DesymfonyTemplate;abstract class MiTwigTemplate extends Twig_Template{    public function render(array $context)...
TWIG LINTER1.*   BÁSICO INTERMEDIO AVANZADO
$twig = new Twig_Environment($loader, array(..));try {   $twig->parse($twig->tokenize($plantilla));   echo "[OK] La sintax...
$ php app/console twig:lint @MyBundle$ php app/console twig:lint src/Cupon/OfertaBundle/Resources/views/index.html.twig
twig:lint
twig:lintSYMFONY 2.1
twig:lint SYMFONY 2.1DESYMFONY 2013
¡muchas gracias!
Contacto • javier.eguiluz@gmail.com • github.com/javiereguiluz • twitter.com/javiereguiluz • linkd.in/javiereguiluz
Upcoming SlideShare
Loading in...5
×

Twig, los mejores trucos y técnicas avanzadas

10,494

Published on

Published in: Technology, Education

Transcript of "Twig, los mejores trucos y técnicas avanzadas"

  1. 1. Twig, los mejores trucos ytécnicas avanzadasJavier EguíluzUniversitat Jaume I · Castellón · 15-16 junio 2012 · desymfony.com
  2. 2. ¡muchas gracias a nuestros patrocinadores! PATROCINADOR PLATINOPATROCINADORES OROPATROCINADORES PLATAPATROCINADORES BRONCE
  3. 3. Agenda • Buenas prácticas • Técnicas avanzadas • Trucos y cosas nuevas
  4. 4. CódigoEl código fuente de los ejemplosmás avanzados de esta ponenciaestá disponible en:https://github.com/javiereguiluz/desymfony!twig
  5. 5. PERSONALIZACIÓN EXTREMA DE FORMULARIOS1.* BÁSICO INTERMEDIO AVANZADO
  6. 6. <div> {{ form_label(form.nombre) }} {{ form_errors(form.nombre) }} {{ form_widget(form.nombre) }}</div>
  7. 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. 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. 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. 10. {% form_theme form _self %}{% block _formulario_nombre_widget %} <div class="especial"><strong> {{ block(field_widget) }} </strong></div>{% endblock %}{{ form_widget(form.nombre) }}
  11. 11. {% form_theme form _self %}{% block _formulario_nombre_widget %} <div class="especial"><strong> {{ block(field_widget) }} </strong></div>{% endblock %}{{ form_widget(form.nombre) }}
  12. 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. 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. 14. <strong>Label</strong>: Valor
  15. 15. <strong>Label</strong>: Valor<strong>{{ form.nombreCampo.vars.label }}</strong>:{{ form. nombreCampo.vars.value }}
  16. 16. <strong>Label</strong>: Valor<strong>{{ form.nombreCampo.vars.label }}</strong>:{{ form. nombreCampo.vars.value }}
  17. 17. CONSTANTES1.* BÁSICO INTERMEDIO AVANZADO
  18. 18. {{ constant() }}
  19. 19. {{ constant(SymfonyComponentHttpKernelKernel::VERSION) }}
  20. 20. {{ constant(SymfonyComponentHttpKernelKernel::VERSION) }}namespace SymfonyComponentHttpKernel;abstract class Kernel implements KernelInterface{ // ... const VERSION = 2.0.15;}
  21. 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. 22. REDEFINE LOS FILTROS POR DEFECTO1.* BÁSICO INTERMEDIO AVANZADO
  23. 23. {{ array|sort }}
  24. 24. asort() array_multisort()arsort() natcasesort()krsort() natsort()ksort() rsort()rsort() shuffle()shuffle() uasort()sort() uksort()usort()
  25. 25. ¿Dónde se definenlos filtros, etiquetas y tags de Twig?
  26. 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. 27. {{ array|sort }}/** * Sorts an array. * * @param array $array An array */function twig_sort_filter($array){ asort($array); return $array;}
  28. 28. natcasesort()a0, A1, a2, a10, ...
  29. 29. class MiCoreExtension extends Twig_Extension_Core { // ...}
  30. 30. class MiCoreExtension extends Twig_Extension_Core { public function getFilters() { // ... }}
  31. 31. class MiCoreExtension extends Twig_Extension_Core { public function getFilters() { return array_merge( parent::getFilters(), array( ... ) ); }}
  32. 32. $twig = new Twig_Environment($loader, array( ... ));$twig->addExtension(new MiCoreExtension());
  33. 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. 34. {{ array|sort }}function twig_sort_filter($array){ natcasesort($array); return $array;}
  35. 35. TODO SON EXPRESIONES1.5 BÁSICO INTERMEDIO AVANZADO
  36. 36. {% include seccion_ ~ oferta.categoria ~ .twig %}{% for i in (1+3)//2..2**(3-1) %}{% endfor %}
  37. 37. {% set ofertas = { (oferta ~ oferta.id): ..., (3 ~ _ ~ oferta.nombre|length): ..., (2**2+1): ...} %}
  38. 38. {% set ofertas = { (oferta ~ oferta.id): ..., (3 ~ _ ~ oferta.nombre|length): ..., (2**2+1): ...} %}
  39. 39. {% set ofertas = { oferta7040: ..., 3_57: ..., 5: ...} %}
  40. 40. EMBED1.8 BÁSICO INTERMEDIO AVANZADO
  41. 41. {% include %} {% extends %} {% embed %}
  42. 42. {% include ... %}
  43. 43. {% extends ... %}
  44. 44. {% embed ... %}
  45. 45. {% embed "lateral.twig" %} {% block principal %} ... {% endblock %}{% endembed %}
  46. 46. {% embed "lateral.twig" %} {% block secundario %} ... {% endblock %}{% endembed %}
  47. 47. {% include plantilla.twig %}{% embed plantilla.twig %}{% endembed %}
  48. 48. ESCAPING AUTOMÁTICO1.8 BÁSICO INTERMEDIO AVANZADO
  49. 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. 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. 51. {{ variable|e }}{{ variable|e(html) }}{{ variable|escape(js) }}{{ variable|e(js) }}{% autoescape %} ........... {% endautoescape %}{% autoescape html %} ... {% endautoescape %}{% autoescape js %} ....... {% endautoescape %}{% autoescape false %} .... {% endautoescape %}
  52. 52. $twig = new Twig_Environment($loader, array( autoescape => function($nombre_plantilla) { return decide_escape($nombre_plantilla); }));
  53. 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. 54. RANDOM1.6 BÁSICO INTERMEDIO AVANZADO
  55. 55. {{ random() }}
  56. 56. {{ random() }}{{ random(10) }}
  57. 57. {{ random() }}{{ random(10) }}{{ random("abcde") }}
  58. 58. {{ random() }}{{ random(10) }}{{ random("abcde") }}{{ random([a, b, c]) }}
  59. 59. FUNCIONES DINÁMICAS1.5 BÁSICO INTERMEDIO AVANZADO
  60. 60. the_ID()the_title()the_time()the_content()the_category()the_shortlink()
  61. 61. the_ID()the_title()the_time()the_content()the_category()the_shortlink()
  62. 62. the_ID()the_title()the_time()the_content()the_category()the_shortlink()the_*()
  63. 63. $twig->addFunction( the_*, new Twig_Function_Function(wordpress));function wordpress($funcion, $opciones){ // ...}
  64. 64. $twig->addFunction( the_*, new Twig_Function_Function(wordpress));function wordpress($funcion, $opciones){ // ...}
  65. 65. {{ the_ID() }}
  66. 66. {{ the_ID() }}function wordpress(ID, array()) { ... }
  67. 67. {{ the_ID() }}function wordpress(ID, array()) { ... }{{ the_content() }}
  68. 68. {{ the_ID() }}function wordpress(ID, array()) { ... }{{ the_content() }}function wordpress(content, array()){ ... }
  69. 69. {{ the_title(<h3>, </h3>) }}function wordpress(title, array( <h3>, </h3>)) { ... }
  70. 70. *_*_link()next_image_link()next_post_link()next_posts_link()previous_image_link()previous_post_link()previous_posts_link()
  71. 71. php_*()
  72. 72. FILTROS DINÁMICOS1.5 BÁSICO INTERMEDIO AVANZADO
  73. 73. {{ now|fecha_corta }}{{ now|fecha_larga }}fecha_*()
  74. 74. $twig->addFilter( fecha_*, new Twig_Filter_Function(fecha));function fecha($funcion, $opciones){ // ...}
  75. 75. VARIABLES GLOBALES1.* BÁSICO INTERMEDIO AVANZADO
  76. 76. {{ app.security }}{{ app.user }}{{ app.request }}{{ app.session }}{{ app.environment }}{{ app.debug }}
  77. 77. {{ _charset }}{{ _context }}{{ _self }}
  78. 78. {{ _charset }} UTF-8
  79. 79. {{ _context }}{% for i in _context|keys %} {{ i }}{% endfor %}
  80. 80. {{ _context }}{% for i in _context|keys %} {{ i }} app assetic{% endfor %} _parent oferta ciudad_por_defecto ciudadSeleccionada expirada ...
  81. 81. {{ _context }}{% for i in _context|keys %} {{ i }} app assetic{% endfor %} _parent oferta ciudad_por_defecto ciudadSeleccionada expirada ...
  82. 82. {{ _context }}{{ variable|mi_filtro(_context) }}
  83. 83. {{ _context }}{{ variable|mi_filtro(_context) }} SÓLO SI NO HAY OTRO REMEDIO
  84. 84. {{ _self }}Twig_Template
  85. 85. {{ _self }}{{ _self.getTemplateName }}OfertaBundle:Default:includes/oferta.html.twig
  86. 86. {{ _self }}{{ _self.blocks|keys|join(", ") }}title, stylesheets, rss, javascripts,id, body
  87. 87. {{ _self }}{{ _self.blocks|keys|join(", ") }}title, stylesheets, rss, javascripts,id, body SÓLO SI NO HAY OTRO REMEDIO
  88. 88. EL SANDBOX1.* BÁSICO INTERMEDIO AVANZADO
  89. 89. DEMO
  90. 90. DATE1.6 BÁSICO INTERMEDIO AVANZADO
  91. 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. 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. 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. 94. date()
  95. 95. {{ date() }}
  96. 96. {{ date() }}{{ date()|date() }}
  97. 97. {{ date() }}{{ date()|date() }}{{ date()|date("d/m/Y") }}
  98. 98. Tu invitación caduca el{{ date(+2days)|date }}
  99. 99. Tu invitación caduca el{{ date(+2days)|date }}{% if date(fechaNacimiento) < date(-18years) %} ¡Eres menor de edad!{% endif %}
  100. 100. La última sorpresa de#deSymfony se desvelará el{{ date(next Monday)|date() }}
  101. 101. OPERADORES PROPIOS1.* BÁSICO INTERMEDIO AVANZADO
  102. 102. $loader = new Twig_Loader_Filesystem(...);$twig = new Twig_Environment($loader, array(...));$twig->addExtension(new OperatorsExtension());
  103. 103. Operador "quédate con el mayor" {{ 5 >> 2 }} 5 {{ 4 >> 20 }} 20
  104. 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. 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. 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. 107. 2 +3**2 / 4 .. 4-5//2 Operador Precedence != 20 + 30 ** 200
  108. 108. {{ a >> b }} max($a, $b); TWIG PHP
  109. 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. 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. 111. // line 23echo twig_escape_filter($this->env, max(5, 2), "html", null, true);
  112. 112. $compiler ->raw() (literal) ->write() (indentado) ->string() (entrecomillado) ->indent() (indentar) ->outdent() (desindentar);
  113. 113. Operador "cambia claves por valores" PHP array_flip(range(a, z))TWIG {% for i in <->(a..z) %} {{ i }}, {% endfor %}
  114. 114. Operador "cambia claves por valores" PHP array_flip(range(a, z))TWIG {% for i in <->(a..z) %} {{ i }}, {% endfor %}
  115. 115. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(<-> => array( precedence => 50, class => DesymfonyOperatorsFlipOperator, ), array() )); }}
  116. 116. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(<-> => array( precedence => 50, class => DesymfonyOperatorsFlipOperator, ), array() )); }}
  117. 117. class OperatorsExtension extends Twig_Extension{ public function getName() { return OperatorsExtension; } public function getOperators() { return array( array(<-> => array( precedence => 50, class => DesymfonyOperatorsFlipOperator, ), array() )); }}
  118. 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. 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. 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. 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. 122. SUPER CACHÉ1.* BÁSICO INTERMEDIO AVANZADO
  123. 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. 124. $twig = new Twig_Environment( $loader, array(cache => /twigcache));# app/config/config.ymltwig: cache: /twigcache
  125. 125. ETIQUETAS PROPIAS1.* BÁSICO INTERMEDIO AVANZADO
  126. 126. etiquetasoperadores #1 tests #2 #3
  127. 127. {% source simple.twig %}{% source ../../../composer.json %}
  128. 128. 1. Clase Token Parser TWIG TWIG2. Clase Node TWIG PHP
  129. 129. $loader = new Twig_Loader_Filesystem(...);$twig = new Twig_Environment($loader, array(...));$twig->addTokenParser(new SourceTokenParser());
  130. 130. {% source ... %}class SourceTokenParser extends Twig_TokenParser{ public function getTag() { return source; }}
  131. 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. 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. 133. // line 3echo file_get_contents("simple.twig");// line 4echo "n";// line 5echo file_get_contents("../../../composer.json");// line 6echo "n";
  134. 134. INTERPOLACIÓN1.5 BÁSICO INTERMEDIO AVANZADO
  135. 135. La oferta cuesta 25.78 euros(30.42 con IVA) y es válidahasta el 10/06/2012
  136. 136. La oferta cuesta 25.78 euros(30.42 con IVA) y es válidahasta el 10/06/2012
  137. 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. 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. 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. 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. 141. {{ "... #{ expresión } ..." }}
  142. 142. {{ "... #{ expresión } ..." }}
  143. 143. NUEVOS FILTROS Y ETIQUETAS1.5 BÁSICO INTERMEDIO AVANZADO
  144. 144. {% flush %}
  145. 145. {% do %}
  146. 146. {{ 1 + 1 }} 2{% do 1 + 1 %} (nada)
  147. 147. {% set lista = [a, b, c, d] %}{{ lista|shift }}{% do lista|shift %}Fuente: https://github.com/fabpot/Twig/issues/446
  148. 148. [:]
  149. 149. {% set lista = [a, b, c, d] %} {{ lista[1:] }}
  150. 150. {% set lista = [a, b, c, d] %} {{ lista[-1:] }}
  151. 151. {% set lista = [a, b, c, d] %} {{ lista[2:2] }}
  152. 152. {{ @username[1:] }}{{ Lorem ipsum...[-4:10] }}
  153. 153. operadores bitwise{{ a b-and b }} $a ^ $b{{ a b-xor b }} $a << $b{{ a b-or b }} $a >> $b TWIG PHP
  154. 154. TWIG_TEMPLATE1.* BÁSICO INTERMEDIO AVANZADO
  155. 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. 156. app/cache/dev/twig/
  157. 157. app/cache/dev/twig/
  158. 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. 159. class __TwigTemplate_09f...2f2 extends Twig_Template{ // ...}
  160. 160. namespace CuponBackendBundleController;use SymfonyBundleFrameworkBundleControllerController;class UsuarioController extends Controller{ public function indexAction() { //... return $this->render( BackendBundle:Usuario:index.html.twig, array( ... ) ); }}
  161. 161. Symfony/Bundle/FrameworkBundle/Controller/Controller.phpfunction render($view, $parameters, $response) { return $this->container->get(templating) ->renderResponse($view, $parameters, $response);}
  162. 162. lib/Twig/Environment.phppublic function render($name, array $context = array()){ return $this->loadTemplate($name) ->render($context);}
  163. 163. return $this->render( ... );render( ... ) Twig_Template
  164. 164. return $this->render( ... );render( ... ) Twig_Template
  165. 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. 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. 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. 168. TWIG LINTER1.* BÁSICO INTERMEDIO AVANZADO
  169. 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. 170. $ php app/console twig:lint @MyBundle$ php app/console twig:lint src/Cupon/OfertaBundle/Resources/views/index.html.twig
  171. 171. twig:lint
  172. 172. twig:lintSYMFONY 2.1
  173. 173. twig:lint SYMFONY 2.1DESYMFONY 2013
  174. 174. ¡muchas gracias!
  175. 175. Contacto • javier.eguiluz@gmail.com • github.com/javiereguiluz • twitter.com/javiereguiluz • linkd.in/javiereguiluz
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×