Twig, cuando Django
encontró a Symfony
Javier Eguiluz



JORNADAS SYMFONY 2011 1-3 JULIO, CASTELLÓN DESYMFONY.COM
Patrocinadores   Patrocinadores   Patrocinadores
Colaboradores      BRONCE            PLATA        PLATINO y ORO    JORNADAS SYMFONY 2011 están patrocinadas por
importante
Algunas partes de esta presentación
no se pueden entender bien sin ver
el vídeo de su impartición.

Puedes acceder al vídeo en
http://bit.ly/sf-tutorial-twig
¿Qué es Twig?
« template engine »
<mensaje>
Hola         <p>Hola
               <contenido>
{ nombre }       Hola José
             José</p>
                 ...
...          ......
...          ...
               </contenido>
             </mensaje>
template engine
        +
template language
twig se puede usar en




               Cualquier
Symfony2     proyecto PHP
Twig para
maquetadores
{# ... #}
{% ... %}
{{ ... }}
{*   *}   <%#   %>   {#   #}
{     }   <%    %>   {%   %}
{$    }   <%=   %>   {{   }}
{% if usuario is defined %}
 Hola {{ usuario.nombre }}
 hoy es {{ 'now' | date('d/m/Y') }}
{% endif %}
Mostrar
información
<p> Hola {{ usuario }}
Tienes {{ edad }} años y vives en
{{ ciudad }} </p>
<p> Hola {{ usuario.nombre }}
Tienes {{ usuario.edad }} años y
vives en {{ usuario.ciudad }} </p>
Modificar
información
{{ descripcion }}
{{ descripcion | striptags }}
{{ etiquetas | join(", ") }}
Hay {{ articulos | length }}
         artículos
{{ titular | striptags | upper }}
<strong>Lorem ipsum</strong>
dolor sit <em>amet</em>
{{ biografia }}
&lt;strong&gt;Lorem ipsum&lt;/
strong&gt; dolor sit
&lt;em&gt;amet&lt;/em&gt;
{{ biografia | raw }}
Espacios
en blanco
<ul>
  <li>
     <a ... >XXX</a>
  </li>

  <li>
     ...
{% spaceless %}
{% spaceless %}
<ul>
  <li>
     <a ... >XXX</a>
  </li>

  <li>
     ...
{% endspaceless %}
<ul><li><a ... >XXX</a></li><li>...
Herencia
de plantillas
« Lo más poderoso
     de Twig »

 Fuente: documentación oficial de Twig
layout.twig
layout.twig




portada.twig          contacto.twig
<html> <head> ... </head>
<body>
  <h1>                </h1>



</body></html>
layout.twig
<html> <head> ... </head>
<body>
  <h1>
   {% block titulo %}{% endblock %}
  </h1>

  {% block cuerpo %}{% endblock %}
</body></html>
portada.twig
{% extends "layout.twig" %}
{% block titulo %}
 Portada
{% endblock %}
{% block cuerpo %}
 Lorem ipsum ...
{% endblock %}
contacto.twig
{% extends "layout.twig" %}
{% block titulo %}
 Contacta con nosotros
{% endblock %}
{% block cuerpo %}
 Duis aute irure dolor in ...
{% endblock %}
1
{% block titulo %}
 Portada
{% endblock %}

{% block titulo "Portada" %}
contacto.twig                   2
{% extends "layout.twig" %}
{% block cuerpo %}
 Duis aute irure dolor in ...
{% endblock %}
layout.twig               3
   ...
   <h1>
     {% block titulo %}
       Lorem Ipsum
     {% endblock %}
   </h1>
   ...
Razones para
   usar Twig
1. Muy fácil de aprender (intuitivo)
2. Suficiente / completo
3. Plantillas concisas y bonitas
Twig para
programadores
Variables
{{ usuario.nombre }}
1.   $usuario["nombre"]
2.   $usuario!>nombre
3.   $usuario!>nombre()
4.   $usuario!>getNombre()
5.   $usuario!>isNombre()
6.   null
{{ usuario.nombre }}
{{ usuario["nombre"] }}
{% set var = "Mi variable" %}
{% set ivas = [4, 8, 18] %}
{%
set nombreCompleto =
 nombre ~ apellidos
%}
{% set perfil %}
  {{ apellidos }}, {{ nombre }}
  {{ edad }} años
  Página: {{ url }}
{% endset %}
Espacios
en blanco
{% spaceless %}
{{ descripcion }}
{{! descripcion }}
{{ descripcion !}}
{{! descripcion !}}
{{ descripcion }}
{{! descripcion }} ltrim(descripcion)
{{ descripcion !}} rtrim(descripcion)
{{! descripcion !}} trim(descripcion)
Filtros
{{ titular | striptags | upper }}
{% filter striptags | upper %}
titular
{% endfilter %}
{{ articulo | truncate(150) }}
{{ articulo | truncate(150, true) }}
Mecanismo
 de escape
« Twig por defecto escapa
   todas las variables »
{{ variable | raw }}
{{ variable | e }}
twig:
  autoescape: true
              false
              js
Estructura
de control for
Taversable
                  Countable




                 {
{% for articulo in articulos %}
  ...
{% endfor %}
{% for i in 0..10 %}
 ...
{% endfor %}
{% for i in 'a'..'z' %}
 ...
{% endfor %}
{% for articulo in articulos %}
  ...
{% else %}
  No existen artículos
{% endfor %}
{% for . in . %}   {% for . in . %}
  ...                ...
{% empty %}        {% else %}
  ...                ...
{% endfor %}       {% endfor %}
variables dentro del for
loop.index    loop.revindex
loop.index0   loop.revindex0

loop.first
              loop.parent
loop.last
loop.length
{% for articulo in articulos %}
 articulo número {{ loop.index }}
{% endfor %}
{% for articulo in articulos %}
 {% if not loop.first %}
    Anterior
 {% endif %}
 {% if not loop.last %}
   Siguiente
 {% endif %}
{% endfor %}
{% for seccion in secciones %}
 {% for categoria in categorias %}
    {{ loop.parent.loop.index }}
    {{ loop.index }}
 {% endfor %}
{% endfor %}
{% for clave in variable | keys %}
 ...
{% endfor %}
{% for clave, valor in variable %}
 ...
{% endfor %}
Estructura
de control if
{% if conectado %}
  ...
{% elseif registrado %}
  ...
{% else %}
  ...
{% endif %}
{% if numero is divisibleby(3) %}
{% if texto is none %}

{% if numero is even %}
 {% if numero is odd %}
{% if descripcion is empty %}

  if (descripcion == null ||
      descripcion == false ||
      descripcion == "") {
    ...
  }
{{ app.user ? 'Mi perfil' :
               'Registrate' }}
Herencia
de plantillas
{% extends "layout.twig" %}
{% extends seccion ~ "_layout.twig" %}
{% extends
seccion | default("principal") ~
"_layout.twig"
%}
{% extends
app.user ? "conectado.html" :
           "anonimo.html"
%}
layout.twig
<html>
<head>
  <title>   </title>
</head>
<body>
    <h1>    </h1>
<html>
<head>
                          layout.twig
  <title>
    {% block titulo %}{% endblock %}
  </title>
</head>
<body>
  <h1>
    {% block titulo %}{% endblock %}
  </h1>
<html>
<head>                      layout.twig
  <title>
    {% block titulo %}{% endblock %}
  </title>
</head>
<body>
  <h1>
     {{ block('title') }}
  </h1>
{% block lateral %}
{% endblock %}        ponencias.twig
   layout.twig
ponencias.twig

{% block lateral %}
  <h3>¿Echas en falta algún tema?</h3>
  <p>...</p>

  {{ parent( ) }}
{% endblock %}
{% block contenidos %}
  {% block principal %}
     ...
  {% endblock %}
{% endblock %}
{% block contenidos %}
  {% block principal %}
     ...
  {% endblock principal %}
{% endblock contenidos %}
Herencia
horizontal
portada.twig
...
{% for articulo in articulos %}
    {{ articulo. titulo }}
{% endfor %}
...
listado.twig


{% for articulo in articulos %}
  {{ articulo. titulo }}
{% endfor %}
portada.twig


...
{% include "listado.twig" %}
...
portada.twig


...
{% include "listado.twig" only %}
...
{% include "listado.html" with
{ 'articulos': articulos } only %}
listado.twig


{% for articulo items %} %}
        item in in articulos
  {{ articulo. titulo }}
     item. titulo }}
{% endfor %}
{% include "listado.html"
   with { 'items': articulos } %}
{% set articulos =
   destacados | merge(otros) %}

{% include "listado.html"
   with { 'items': articulos }
   only %}
Extensiones
« Twig está construido
   con extensiones »
Macro     Tag
Filtro    Test
Función   Operator
Global
Para generar   Para modificar
  contenido       contenido

 Macro
                  Filtro
Función
https://github.com /
fabpot /
Twig!extensions
Filtros
{{ ponente.biografia | auto_link_text }}
DesymfonyBundleExtensionDesymfonyTwigExtension.php

class DesymfonyTwigExtension extends Twig_Extension {
   public function getFilters() {
     return array(
        'auto_link_text' => new Twig_Filter_Method (
            $this, 'auto_link_text'
        ));
   }

  static public function auto_link_text($string) {
     ...
     return $string;
  }
{{ ponente.biografia
   | auto_link_text
   | raw }}
DesymfonyBundleExtensionDesymfonyTwigExtension.php




public function getFilters() {
  return array(
   'auto_link_text' => new Twig_Filter_Method (
       $this, 'auto_link_text'
   ));
}
DesymfonyBundleExtensionDesymfonyTwigExtension.php




public function getFilters() {
  return array(
   'auto_link_text' => new Twig_Filter_Method (
       $this, 'auto_link_text',
       array('is_safe' => array('html'))
   ));
}
{{ ponente.biografia
   | auto_link_text
   | raw }}
Macros
« El equivalente en Twig a las
funciones de programación »
{% macro input(name, type) %}
  <input type="{{ type }}"
         name="{{ name }}" />
{% endmacro %}
{% macro input(name, type) %}
  ...
{% endmacro %}

<div>{{ _self.input('edad') }}</div>

 <input type="" name="edad" />
{% macro input(name, type) %}
  ...
{% endmacro %}

<div>{{ _self.input('edad', 'text') }}</div>


<input type="text" name="edad" />
{% macro input(name, type) %}
<input type="{{ type | default('text') }}"
      name="{{ name }}" />
{% endmacro %}
formularios.twig

{% macro input(name, type) %}
  <input type="{{ type }}"
         name="{{ name }}" />
{% endmacro %}
pagina.twig
{% import "formularios.twig"
   as formularios %}
<div>
  {{ formularios.input('edad') }}
</div>
Twig en
Symfony2
{{"path( ) }}   {% trans %}
 {{ url( ) }}

   caché        las plantillas se
 configurada      cargan solas
app/cache/dev/twig
/* DesymfonyBundle:Default:index.html.twig */
class __TwigTemplate_8e822424720fee931876b7c05a9112b0 extends Twig_Template
{
   protected $parent;

  public function __construct(Twig_Environment $env)
  {
    parent::__construct($env);

    $this!>blocks = array(
       'title' => array($this, 'block_title'),
       'pageid' => array($this, 'block_pageid'),
       'contenido' => array($this, 'block_contenido'),
    );
Twig fuera de
   Symfony2
1. Descargar Twig
2. Registrar su autoloader
EN LA PRÁCTICA




     Usando Twig en un
    proyecto PHP propio
Referencias
http://twig!project.org
Razones para
   usar Twig
Proyecto maduro y
    completo
La ¿única? posibilidad
para los maquetadores
Fácilmente extensible
Rendimiento
comparable a PHP
contacto
javier.eguiluz@gmail.com
twitter.com/javiereguiluz
linkedin.com/in/javiereguiluz

Desymfony 2011 - Twig