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, 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

12,732 views

Published on

Published in: Technology, Education

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

×