SlideShare a Scribd company logo
1 of 228
Download to read offline
Twig avanzado
Javier Eguiluz


     Jornadas Symfony2 Galicia
     25-26 noviembre 2011        #sf2Vigo
me presento
 •   Javier Eguiluz
 •   formador en Symfony2 y
     nuevas tecnologías
creador de http://symfony.es
apasionado de Symfony
           http://connect.sensiolabs.com/
                 profile/javier.eguiluz
objetivos de la sesión
 •   Buenas prácticas
 •   Trucos
 •   Usos avanzados
 •   Snipets
Si no sabes Twig, te vas a
   perder a partir de la
 siguiente transparencia
Aprende Twig
en 5 minutos
«Twig es un lenguaje y
motor de plantillas PHP»
twig se puede usar en




               Cualquier
Symfony2     proyecto PHP
¿Por qué usar
       Twig?
$usuario

public function getNombre()
{
  return $this->nombre;
}
TWIG




{{ usuario.nombre }}
PHP




echo $usuario->getNombre()
PHP




<?php
echo $usuario->getNombre();
?>
PHP

<?php
echo htmlspecialchars(
   $usuario->getNombre(),
   ENT_QUOTES,
   'UTF-8');
?>
TWIG


    {{ usuario.nombre }}

                                   PHP

<?php echo htmlspecialchars($usuario->
getNombre(), ENT_QUOTES, 'UTF-8'); ?>
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>
{{ usuario.nombre }}
{{ usuario.nombre }}
1.   $usuario["nombre"]
2.   $usuario->nombre
3.   $usuario->nombre()
4.   $usuario->getNombre()
5.   $usuario->isNombre()
6.   null
<?php             Template.php
abstract class   Twig_Template   implements
                                 Twig_TemplateInterface
{

    // ...

    protected function getAttribute(
        $object,
        $item,
        array $arguments = array(),
        $type = Twig_TemplateInterface::ANY_CALL,
        $isDefinedTest = false) {

        // ...
twig-ext

Derick Rethans
http://github.com/derickr/twig-ext
Modificar
información
{{ descripcion }}
{{ descripcion | striptags }}
{{ 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>...
Estructuras
 de control
{% for elemento in coleccion %}

   {# ... #}

{% endfor %}
{% for clave, elemento
   in coleccion %}

   {# ... #}

{% endfor %}
{% if condicion1 %}
  {# ... #}
{% elseif condicion2 %}
  {# ... #}
{% else %}
  {# ... #}
{% endif %}
Herencia
de plantillas
PORTADA
CONTACTO
# TITULO #




                    # LATERAL #
   # CONTENIDOS #
# TITULO #          layout.twig




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

    {% block contenidos %}{% endblock %}
    {% block lateral %}{% endblock %}
</body></html>
<html> <head> ... </head>   portada.twig
<body>
    <h1>
       PORTADA
    </h1>

    <div id="contenidos">...</div>
    <div id="lateral">...</div>
</body></html>
<html> <head> ... </head>   portada.twig
<body>
    <h1>
       PORTADA
    </h1>

    <div id="contenidos">...</div>
    <div id="lateral">...</div>
</body></html>
portada.twig


  PORTADA



<div id="contenidos">...</div>
<div id="lateral">...</div>
portada.twig
{% extends "layout.twig"   %}


     PORTADA



   <div id="contenidos">...</div>
   <div id="lateral">...</div>
{% extends "layout.twig" %} portada.twig

{% block titulo %}
  PORTADA
{% endblock %}

{% block contenidos %}
  <div id="contenidos">...</div>
{% endblock %}

{% block lateral %}
  <div id="lateral">...</div>
{% endblock %}
{% extends "layout.twig" %}
                          contacto.twig
{% block titulo %}
  CONTACTO
{% endblock %}

{% block contenidos %}
  <form>...</form>
{% endblock %}

{% block lateral %}
  <p>...</p>
{% endblock %}
ya pasaron los
5 minutos
DESARROLLO
WEB ÁGIL CON        todos los ejemplos que se muestran
SYMFONY2             a continuación pertenecen al libro

                    Desarrollo web ágil
                      con Symfony2
                        (disponible próximamente)

   Javier Eguiluz
variables
 globales
# app/config/config.yml
twig:
    # ...
    globals:
        cp:       01001
        iva:      [1.04, 1.08, 1.18]
        version: 1.0.3
# app/config/config.yml
twig:
    # ...
    globals:
        cp:       01001
        iva:      [1.04, 1.08, 1.18]
        version: 1.0.3



Precio {{ oferta.precio * iva[0] }}


Coste de envío a {{ usuario.cp | default(cp) }}


<footer>
    &copy; 'now'|date('Y') - v.{{ version }}
</footer>
# app/config/config.yml
twig:
    # ...
    globals:
        global:
             cp:      01001
             iva:     [1.04, 1.08, 1.18]
             version: 1.0.3
# app/config/config.yml
twig:
    # ...
    globals:
        global:
             cp:      01001
             iva:     [1.04, 1.08, 1.18]
             version: 1.0.3



Precio {{ oferta.precio * global.iva[0] }}


Coste de envío a {{ oferta.cp | default(global.cp) }}


<footer>
    &copy; 'now'|date('Y') - v.{{ global.version }}
</footer>
servicios como variables globales
namespace CuponOfertaBundleUtil;

class Util
{
  static public function getSlug($cadena)
  {
    // ...
    return $slug;
  }
}
# app/config/config.yml
services:
  # ...
  cupon.utilidades:
    class: CuponOfertaBundleUtilUtil
# app/config/config.yml
twig:
    # ...
    globals:
        utilidades: @cupon.utilidades
# app/config/config.yml
twig:
    # ...
    globals:
        utilidades: @cupon.utilidades
{{ utilidades.getSlug('Lorem ipsum
dolor sit amet') }}
depurando
 variables
<?php var_dump($oferta); ?>


{% debug oferta %}
# app/config/config.yml
services:
    twig.extension.debug:
        class: Twig_Extensions_Extension_Debug
        tags:
            - { name: twig.extension }
for ... else
{% for articulo in articulos %}
  {{ articulo.titulo }}
  {# ... #}
{% endfor %}
{% for articulo in articulos %}
  {{ articulo.titulo }}
  {# ... #}
{% else %}
  No hay artículos
{% endfor %}
for ... if
Itera sólamente por las
     ofertas baratas
{% for oferta in ofertas
   if oferta.precio < 10 %}

  {# ... #}

{% endfor %}
1.2


{% for elemento in coleccion
   if condicion %}

  {# ... #}

{% endfor %}
Itera sólamente por los
     amigos del usuario
{% set usuarios = 1..30 %}
{% set amigos = [12, 29, 34, 55, 67] %}
{% 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 %}
Operadores
de división
operación      resultado
{{ 12 / 7 }}    1.7142857142

{{ 12 // 7 }}        1

{{ 12 % 7 }}         5
creando
variables
{% set nombre = 'José García' %}

{% set edad = 27 %}
{% set precio = 104.83 %}

{% set conectado = false %}

{% set tasaImpuestos = [4, 8, 18] %}
{% set perfil =    {
     'nombre':     'José García',
     'perfiles':   ['usuario', 'admin'],
     'edad':       27,
     'validado':   true
} %}
{% set nombreCompleto = nombre ~ ' ' ~
                        apellidos %}


{% set experiencia = edad ~ ' años' %}
{% set perfil %}
 Nombre: {{ usuario.nombre }}
 Apellidos: {{ usuario.apellidos }}
 Edad: {{ usuario.edad }} años
 Página: {{ usuario.url }}
{% endset %}

{{ perfil }}
{% set nombre, edad, activado =
   'José', 27, false %}


{{ nombre }}
{{ edad }}
{% if activado %}
espacios
en blanco
class DefaultController extends Controller
{
    {% if comentarios %}
    /**
     * Primera línea
     * Segunda línea
     */
    {% endif %}
NO


class DefaultController extends Controller
{
    /**
     * Primera línea
     * Segunda línea
     */
SI


class DefaultController extends Controller
{
        /**
     * Primera línea
     * Segunda línea
     */
SI


class DefaultController extends Controller
{
        /**
     * Primera línea
     * Segunda línea
     */
class DefaultController extends Controller
{
    {% if comentarios %}
    /**
     * Primera línea
     * Segunda línea
     */
    {% endif %}
class DefaultController extends Controller
{
    {% if comentarios %}
    /**
     * Primera línea
     * Segunda línea
     */
    {% endif %}
class DefaultController extends Controller
{
{% if comentarios %}
    /**
     * Primera línea
     * Segunda línea
     */
{% endif %}
SI


class DefaultController extends Controller
{
    /**
     * Primera línea
     * Segunda línea
     */
class DefaultController extends Controller
{
    {% if comentarios %}
    /**
     * Primera línea
     * Segunda línea
     */
    {% endif %}
class DefaultController extends Controller
{
    {% if comentarios -%}
    /**
     * Primera línea
     * Segunda línea
     */
    {%- endif %}
SI


class DefaultController extends Controller
{
    /**
     * Primera línea
     * Segunda línea
     */
{% if condicion -%}

  {# ... #}

{%- endif %}
class DefaultController extends Controller
{
    {% if comentarios -%}
    /**
     * Comentario
     */
    {%- else -%}
    /**
     * @Anotacion(...)
     */
    {%- endif %}
formatear
información
{{ '%.0f'|format(time * 1000) }} ms
{{ '%.0f'|format(time * 1000) }} ms
{{ '%.0f'|format(time * 1000) }} ms
{{ '%.0f'|format(time * 1000) }} ms




{{ '%0.2f'|format(time * 1000) }} ms
macros
polimórficas
{# formulario.html.twig #}
{% macro campo(nombre, tipo, valor) %}
    <input type="{{ tipo }}"
           name="{{ nombre }}"
           value="{{ valor }}" />
{% endmacro %}
{% from 'formularios.html.twig'
   import campo as campo %}
{% from 'formularios.html.twig'
   import campo as campo %}

<table>
    {{ campo('nombre', 'text', 'José') }}
    {{ campo('apellidos', 'text', 'García Pérez') }}
    {{ campo('telefono', 'text') }}
</table>
{% 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>
{# formulario.html.twig #}
{% macro campo(nombre, tipo, valor) %}
    <input type="{{ tipo }}" name="{{ nombre }}"
           value="{{ valor }}" />
{% endmacro %}
{# 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 %}
{# formulario.html.twig #}
{% macro campo(nombre, tipo, valor) %}
    <input type="{{ tipo }}" name="{{ nombre }}"
           value="{{ valor }}" />
{% endmacro %}
{# 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 %}
{% from 'formularios.html.twig'
   import campo as campo %}



    {{ campo('nombre', 'text', 'José') }}
    {{ campo('apellidos', 'text', 'García Pérez') }}
    {{ campo('telefono', 'text') }}
{% from 'formularios.html.twig'
   import fila as campo %}

<table>
    {{ campo('nombre', 'text', 'José') }}
    {{ campo('apellidos', 'text', 'García Pérez') }}
    {{ campo('telefono', 'text') }}
</table>
{% from 'formularios.html.twig'
   import item as campo %}

<ul>
    {{ campo('nombre', 'text', 'José') }}
    {{ campo('apellidos', 'text', 'García Pérez') }}
    {{ campo('telefono', 'text') }}
</ul>
filtros dependientes
         del entorno
public function getFilters()
{
  return array('longitud' => new
     Twig_Filter_Method($this,
                         'longitud')
  );
}

function longitud($valor)
{
    return strlen($valor);
}
public function getFilters()
{
  return array('longitud' => new
     Twig_Filter_Method($this,
                         'longitud')
  );
}

function longitud($valor)
{
    return strlen($valor);
}
function longitud($valor)
{
   return mb_strlen($valor, 'EUC-JP');
}
public function getFilters()
{
    return array(
        'longitud' => new Twig_Filter_Method(
            $this,
            'longitud',
            array('needs_environment' => true)
        )
    );
}
public function getFilters()
{
    return array(
        'longitud' => new Twig_Filter_Method(
            $this,
            'longitud',
            array('needs_environment' => true)
        )
    );
}
function longitud(Twig_Environment $entorno, $valor)
{
    $codificacion = $entorno->getCharset();
    return mb_strlen($valor, $codificacion);
}
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);
    // ...
}
notación
 bundle
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}

      src/MiAplicacion/
          MiBundle/
              Resources/
                   views/
                       Carpeta/
                       plantilla.html.twig
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}


{% include 'MiBundle:Carpeta:Subcarpeta/
            plantilla.html.twig' %}
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}


{% include 'MiBundle:Carpeta:Subcarpeta/
            plantilla.html.twig' %}


{% include 'MiBundle:Carpeta:Subcarpeta1/
   Subcarpeta2/plantilla.html.twig' %}
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}


{% include
'MiBundle::Carpeta/plantilla.html.twig' %}
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}
{% include
'MiBundle:Carpeta:plantilla.html.twig' %}


{% include
'views/Carpeta/plantilla.html.twig' %}
opciones de
configuración
# app/config/config.yml
twig:
    autoescape:           true
    auto_reload:          ~
    cache:                %kernel.cache_dir%/twig
    charset:              %kernel.charset%
    debug:                %kernel.debug%
    strict_variables:     ~
$twig = new Twig_Environment($loader, array(
    'debug'    => true,
    'strict_variables' => true,
    'charset' => 'UTF-8',
    'cache'    => __DIR__.'/cache'
));
# app/config/config.yml
 twig:
     base_template_class:   Twig_Template


<?php

class __TwigTemplate_82262eae3f96052ef64432a9ddc53915
      extends Twig_Template
{
    protected $parent;

    public function __construct(Twig_Environment $env)
    {
        // ...
    }
# app/config/config.yml
 twig:
     base_template_class:   Twig_Template


<?php

class __TwigTemplate_82262eae3f96052ef64432a9ddc53915
      extends Twig_Template
{
    protected $parent;

    public function __construct(Twig_Environment $env)
    {
        // ...
    }
# app/config/config.yml
twig:
    # ...
    exception_controller: SymfonyBundleTwigBundle
ControllerExceptionController::showAction
# app/config/config.yml
twig:
    # ...
    form:
        resources: [ ... ]
formularios
personalizados
modificar campos de una plantilla
{{ form_row(noticia.url) }}
modificar campos de una plantilla
{{ form_row(noticia.url) }}

Label
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 %}
{{ form_row(noticia.url) }}


{% form_theme form _self %}

{% block url_widget %}
 {% set type = 'url' %}
 <em>http://</em> {{ block('field_widget') }}
{% endblock url_widget %}
{{ form_row(noticia.url) }}


{% form_theme form _self %}

{% block url_widget %}
 {% set type = 'url' %}
 <em>http://</em> {{ block('field_widget') }}
{% endblock url_widget %}
{{ 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://
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 %}
{% form_theme form
   'MiBundle:Form:form.html.twig' %}


{{ form_row(noticia.titular) }}

{{ form_row(noticia.publicada) }}

{{ form_row(noticia.url) }}
modificar todos los formularios
# app/config/config.yml
twig:
  # ...
  form:
    resources:
      - 'form_div_layout.html.twig'
# app/config/config.yml
twig:
  # ...
  form:
    resources:
      - 'form_table_layout.html.twig'
{% 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 %}

{# ... #}
{% use "form_div_layout.html.twig" %}
{% block field_row %}
    {# ... #}
{% endblock %}

{% block form_errors %}
    {# ... #}
{% endblock %}

{% block hidden_row %}
    {# ... #}
{% endblock %}

{% block form_widget %}
    {# ... #}
{% endblock %}
# app/config/config.yml
twig:
  # ...
  form:
    resources:
      - 'MiBundle:Form:form.html.twig'
mostrando
campos de fecha
{{ form_row(fecha) }}
{{ form_label(fecha) }}
{{ form_errors(fecha) }}

{{ form_widget(fecha) }}
{{ form_label(fecha) }}
{{ form_errors(fecha) }}

{{ form_widget(fecha.year) }}
{{ form_widget(fecha.month) }}
{{ form_widget(fecha.day) }}
generando
   código
«Twig genera con
facilidad cualquier tipo
     de contenido»
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 %}
}
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 {
        /* ... */
    }
{% block NamespaceDeclaration %}
{% if namespace %}                                      Doctrine2
namespace {{ namespace }};                           ActiveRecord
use {{ 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 %}
}
https://github.com/
cedriclombardot/
TwigGenerator
twig.js
<select id="ciudad">
    {% for ciudad in ciudades %}
    <option value="{{ ciudad.slug }}">
        {{ ciudad.nombre }}
    </option>
    {% endfor %}
</select>
<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>
<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>
<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>
<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>
https://github.com/
FriendsOfSymfony/
FOSJsRoutingBundle
{% twig_js name="perfil" %}
Nombre: {{ nombre }}
Apellidos: {{ apellidos }}
{% twig_js name="perfil" %}
Nombre: {{ nombre }}
Apellidos: {{ apellidos }}
<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>
https://github.com/
schmittjoh/
twig.js
flexible
{{ ... | length }}



Tienes {{ amigos|length }} amigos
y tu nombre tiene
{{ nombre|length }} letras
{{ ... | length }}

                   count( )
Tienes {{ amigos|length }} amigos
y tu nombre tiene
{{ nombre|length }} letras
{{ ... | length }}

                        count( )
Tienes {{ amigos|length }} amigos
y tu nombre tiene
{{ nombre|length }} letras

            strlen( )
{{ ... 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 %}
{{ ... 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 %}
{{ ... 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 %}
{% for letra in 'a'|upper..inicial|default('z')|upper %}
    {{ letra }}
{% endfor %}
{% 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'|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 %}
propiedades
   variables
{{ objeto.propiedad }}
{{ objeto.propiedad }}
{% set bundles = {
     'AsseticBundle'    =>   '.../vendor/...',
     'BackendBundle'    =>   '.../src/...',
     'CiudadBundle'     =>   '.../src/...',
     'DoctrineBundle'   =>   '.../vendor/...',
     ...
} %}
NO




{{ bundles.'AsseticBundle' }}
SI




{% set nombre = 'AsseticBundle' %}

{{ bundles[nombre] }}
{% for name in bundles|keys|sort %}
<tr>
     <th>{{ name }}</th>
     <td>{{ bundles[name] }}</td>
</tr>
{% endfor %}
{% set usuarios = [
     { 'email': '..@..' },
     { 'movil': '9....' }
] %}
{% set usuarios = [
     { 'email': '..@..' },
     { 'movil': '9....' }
] %}


{% for usuario in usuarios %}
  {{ usuario.nombre }}
  Contacto {{ usuario.????? }}
{% endfor %}
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}


 {{ usuario.contacto }}


 resultado   email
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}


 {{ usuario[contacto] }}


 resultado   ERROR
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}


 {{ usuario[usuario.contacto] }}


 resultado   ..@..
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}


 {{ attribute(usuario, usuario.contacto) }}
{% set usuarios = [
 { 'email': '..@..', 'contacto': 'email' },
 { 'movil': '9....', 'contacto': 'movil' }
] %}


 {{ attribute(usuario, usuario.contacto) }}


 resultado   ..@..
1.2

{{ attribute(objeto, propiedad) }}


{{ attribute(objeto, expresion) }}


{{ attribute(producto, 'foto' ~ i) }}
1.2

{{ attribute(objeto, metodo) }}



{{ attribute(objeto, metodo,
             argumentos) }}
herencia
dinámica
{% extends usuario.tipo ~ '.html.twig' %}


{# usuario = {'tipo': 'admin'} #}
admin.html.twig

{# usuario = {'tipo': 'usuario'} #}
usuario.html.twig
{% extends listado ?
     'listado.html.twig'
     :
     'tabla.html.twig' %}
1.2




{% extends ['primera.html.twig',
            'segunda.html.twig',
            'tercera.html.twig'] %}
{% extends 'noticia.html.twig' %}
{% extends [
'categoria_' ~ noticia.categoria ~ '.html.twig',
'seccion_' ~ noticia.seccion ~ '.html.twig',
'noticia.html.twig'
] %}
include
dinámico
1.2




{% include ['primera.html.twig',
            'segunda.html.twig',
            'tercera.html.twig'] %}
{% include [
'lateral_' ~ noticia.categoria ~ '.html.twig',
'lateral_' ~ noticia.seccion ~ '.html.twig',
'lateral.html.twig'
] %}
{% set seccion = ... %}

{% include
   'lateral_' ~ seccion ~ '.html.twig'
%}
1.2


{% set seccion = ... %}

{% include
   'lateral_' ~ seccion ~ '.html.twig'
   ignore missing
%}
{% include '...' ignore missing %}

{% include '...' ignore missing
   with { ... } %}

{% include '...' ignore missing
   with { ... } only %}
muchas
gracias
dudas
preguntas
comentarios
contacta
javier.eguiluz@gmail.com

conecta
linkedin.com/in/javiereguiluz
copyright
Los contenidos de esta
presentación son propiedad
de su autor. No se pueden
reutilizar sin el consentimiento
expreso de su autor.

More Related Content

What's hot

Php excel
Php excelPhp excel
Php excel
pcuseth
 
Ejemplos de php_mysql
Ejemplos de php_mysqlEjemplos de php_mysql
Ejemplos de php_mysql
I LG
 
66 Php. Encuadre Y Redimensionado De Imagenes
66 Php. Encuadre Y Redimensionado De Imagenes66 Php. Encuadre Y Redimensionado De Imagenes
66 Php. Encuadre Y Redimensionado De Imagenes
José M. Padilla
 
63 Php. Imagenes Con Lineas Y Textos
63 Php. Imagenes Con Lineas Y Textos63 Php. Imagenes Con Lineas Y Textos
63 Php. Imagenes Con Lineas Y Textos
José M. Padilla
 
Proyecto Base de Datos I
Proyecto Base de Datos IProyecto Base de Datos I
Proyecto Base de Datos I
Marcia Ramos
 

What's hot (20)

Código Bonito con PHP
Código Bonito con PHPCódigo Bonito con PHP
Código Bonito con PHP
 
J query
J queryJ query
J query
 
Wp config.php
Wp config.phpWp config.php
Wp config.php
 
WordCamp Cantabria - Código mantenible con WordPress
WordCamp Cantabria  - Código mantenible con WordPressWordCamp Cantabria  - Código mantenible con WordPress
WordCamp Cantabria - Código mantenible con WordPress
 
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
 
Php excel
Php excelPhp excel
Php excel
 
Ejemplos de php_mysql
Ejemplos de php_mysqlEjemplos de php_mysql
Ejemplos de php_mysql
 
Clase7popu
Clase7popuClase7popu
Clase7popu
 
jQuery 1.3 Eghost Julio2009
jQuery 1.3 Eghost Julio2009jQuery 1.3 Eghost Julio2009
jQuery 1.3 Eghost Julio2009
 
Práctica Completa en Flash – ActionScript
Práctica Completa en Flash – ActionScriptPráctica Completa en Flash – ActionScript
Práctica Completa en Flash – ActionScript
 
66 Php. Encuadre Y Redimensionado De Imagenes
66 Php. Encuadre Y Redimensionado De Imagenes66 Php. Encuadre Y Redimensionado De Imagenes
66 Php. Encuadre Y Redimensionado De Imagenes
 
Angularjs Lógica de negocio
Angularjs Lógica de negocioAngularjs Lógica de negocio
Angularjs Lógica de negocio
 
Charla congreso web introducción programación funcional en JavaScript
Charla congreso web introducción programación funcional en JavaScriptCharla congreso web introducción programación funcional en JavaScript
Charla congreso web introducción programación funcional en JavaScript
 
Funciones
FuncionesFunciones
Funciones
 
Curso Javascript profesionales
Curso Javascript profesionalesCurso Javascript profesionales
Curso Javascript profesionales
 
63 Php. Imagenes Con Lineas Y Textos
63 Php. Imagenes Con Lineas Y Textos63 Php. Imagenes Con Lineas Y Textos
63 Php. Imagenes Con Lineas Y Textos
 
Php funciones en detalle
Php   funciones en detallePhp   funciones en detalle
Php funciones en detalle
 
62 Php. Creando Imagenes
62 Php. Creando Imagenes62 Php. Creando Imagenes
62 Php. Creando Imagenes
 
Perl5 hashes
Perl5 hashesPerl5 hashes
Perl5 hashes
 
Proyecto Base de Datos I
Proyecto Base de Datos IProyecto Base de Datos I
Proyecto Base de Datos I
 

Viewers also liked

Clase 1 introducción a symfony 2
Clase 1   introducción a symfony 2Clase 1   introducción a symfony 2
Clase 1 introducción a symfony 2
hydras_cs
 
Redis–symfony–barcelona–31 05-2012
Redis–symfony–barcelona–31 05-2012Redis–symfony–barcelona–31 05-2012
Redis–symfony–barcelona–31 05-2012
symfony_bcn
 

Viewers also liked (20)

Symfony2 admingenerator
Symfony2 admingeneratorSymfony2 admingenerator
Symfony2 admingenerator
 
Geografía como plataforma: API REST vs OGC y Geodatabases - Conferencia Esri ...
Geografía como plataforma: API REST vs OGC y Geodatabases - Conferencia Esri ...Geografía como plataforma: API REST vs OGC y Geodatabases - Conferencia Esri ...
Geografía como plataforma: API REST vs OGC y Geodatabases - Conferencia Esri ...
 
Modeliza de variables_climaticas2
Modeliza de variables_climaticas2Modeliza de variables_climaticas2
Modeliza de variables_climaticas2
 
Clase 1 introducción a symfony 2
Clase 1   introducción a symfony 2Clase 1   introducción a symfony 2
Clase 1 introducción a symfony 2
 
Eppur si muove - SIG Libre Girona
Eppur si muove - SIG Libre GironaEppur si muove - SIG Libre Girona
Eppur si muove - SIG Libre Girona
 
Mi primer programa en Symfony2
Mi primer programa en Symfony2Mi primer programa en Symfony2
Mi primer programa en Symfony2
 
Paty carbajal presentacion
Paty carbajal presentacionPaty carbajal presentacion
Paty carbajal presentacion
 
Herramientas publicación gis web poroceso y análisis
Herramientas publicación gis web   poroceso y análisisHerramientas publicación gis web   poroceso y análisis
Herramientas publicación gis web poroceso y análisis
 
Monografia Metodologia Agil XP
Monografia Metodologia Agil XPMonografia Metodologia Agil XP
Monografia Metodologia Agil XP
 
Redis–symfony–barcelona–31 05-2012
Redis–symfony–barcelona–31 05-2012Redis–symfony–barcelona–31 05-2012
Redis–symfony–barcelona–31 05-2012
 
Web components
Web componentsWeb components
Web components
 
Metodologia rad XP
Metodologia rad XPMetodologia rad XP
Metodologia rad XP
 
Metodologia xp
Metodologia xpMetodologia xp
Metodologia xp
 
Aplicaciones Machine Learning GIS
Aplicaciones Machine Learning GISAplicaciones Machine Learning GIS
Aplicaciones Machine Learning GIS
 
Metaprogramación Compositiva en JavaScript
Metaprogramación Compositiva en JavaScriptMetaprogramación Compositiva en JavaScript
Metaprogramación Compositiva en JavaScript
 
Symfony2 Formacion y primeros pasos
Symfony2  Formacion y primeros pasosSymfony2  Formacion y primeros pasos
Symfony2 Formacion y primeros pasos
 
Introduccion Sig
Introduccion SigIntroduccion Sig
Introduccion Sig
 
Programación Extrema
Programación ExtremaProgramación Extrema
Programación Extrema
 
SIG en la Web: Fundamentos
SIG en la Web: FundamentosSIG en la Web: Fundamentos
SIG en la Web: Fundamentos
 
Integrando Redis en aplicaciones Symfony2
Integrando Redis en aplicaciones Symfony2Integrando Redis en aplicaciones Symfony2
Integrando Redis en aplicaciones Symfony2
 

Similar to Twig avanzado (sf2Vigo)

Informe grupal f_arinango_ cuenca
Informe grupal f_arinango_ cuencaInforme grupal f_arinango_ cuenca
Informe grupal f_arinango_ cuenca
paulcuenca9
 
Modelo vista controlador
Modelo vista controladorModelo vista controlador
Modelo vista controlador
descarga2009
 
Desarrollando aplicaciones web usando Catalyst y jQuery
Desarrollando aplicaciones web usando Catalyst y jQueryDesarrollando aplicaciones web usando Catalyst y jQuery
Desarrollando aplicaciones web usando Catalyst y jQuery
Javier P.
 

Similar to Twig avanzado (sf2Vigo) (20)

Introducción a DJango
Introducción a DJangoIntroducción a DJango
Introducción a DJango
 
Twig
TwigTwig
Twig
 
Introducción a Flask
Introducción a FlaskIntroducción a Flask
Introducción a Flask
 
Informe grupal f_arinango_ cuenca
Informe grupal f_arinango_ cuencaInforme grupal f_arinango_ cuenca
Informe grupal f_arinango_ cuenca
 
EXAMEN
EXAMENEXAMEN
EXAMEN
 
Empezando con Angular 2
Empezando con Angular 2Empezando con Angular 2
Empezando con Angular 2
 
Parte II. Notas Rapidas (sticky notes) App W8: MVVM y SQLite.
Parte II. Notas Rapidas (sticky notes) App W8: MVVM y SQLite.Parte II. Notas Rapidas (sticky notes) App W8: MVVM y SQLite.
Parte II. Notas Rapidas (sticky notes) App W8: MVVM y SQLite.
 
Modelo vista controlador
Modelo vista controladorModelo vista controlador
Modelo vista controlador
 
Taller introduccion symfony2
Taller introduccion symfony2Taller introduccion symfony2
Taller introduccion symfony2
 
Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6
 
Desarrollando aplicaciones web usando Catalyst y jQuery
Desarrollando aplicaciones web usando Catalyst y jQueryDesarrollando aplicaciones web usando Catalyst y jQuery
Desarrollando aplicaciones web usando Catalyst y jQuery
 
Hands on Spring 2.5
Hands on Spring 2.5Hands on Spring 2.5
Hands on Spring 2.5
 
APIREST LARAVEL Y PHP.pptx
APIREST LARAVEL Y PHP.pptxAPIREST LARAVEL Y PHP.pptx
APIREST LARAVEL Y PHP.pptx
 
Ejemplos c
Ejemplos cEjemplos c
Ejemplos c
 
Desarrollo de aplicaciones web usando Catalyst y jQuery
Desarrollo de aplicaciones web usando Catalyst y jQueryDesarrollo de aplicaciones web usando Catalyst y jQuery
Desarrollo de aplicaciones web usando Catalyst y jQuery
 
Tips Bootstrap 3 en Drupal 7
Tips Bootstrap 3 en Drupal 7Tips Bootstrap 3 en Drupal 7
Tips Bootstrap 3 en Drupal 7
 
Drupal7 para desarrolladores
Drupal7 para desarrolladoresDrupal7 para desarrolladores
Drupal7 para desarrolladores
 
Django: el framework web definitivo
Django: el framework web definitivoDjango: el framework web definitivo
Django: el framework web definitivo
 
Actividad 3 . funciones en php
Actividad 3 . funciones en phpActividad 3 . funciones en php
Actividad 3 . funciones en php
 
Liferay 6.1 Service Builder
Liferay 6.1  Service BuilderLiferay 6.1  Service Builder
Liferay 6.1 Service Builder
 

More from Javier Eguiluz

Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
Javier Eguiluz
 

More from Javier Eguiluz (18)

deSymfony 2017: Symfony 4, Symfony Flex y el futuro de Symfony
deSymfony 2017: Symfony 4, Symfony Flex y el futuro de SymfonydeSymfony 2017: Symfony 4, Symfony Flex y el futuro de Symfony
deSymfony 2017: Symfony 4, Symfony Flex y el futuro de Symfony
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
 
Mastering Twig (DrupalCon Barcelona 2015)
Mastering Twig (DrupalCon Barcelona 2015)Mastering Twig (DrupalCon Barcelona 2015)
Mastering Twig (DrupalCon Barcelona 2015)
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
Silex al límite
Silex al límiteSilex al límite
Silex al límite
 
Twig tips and tricks
Twig tips and tricksTwig tips and tricks
Twig tips and tricks
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
 
Wallpaper Notifier
Wallpaper NotifierWallpaper Notifier
Wallpaper Notifier
 
Desymfony 2012 - Concurso de diseño
Desymfony 2012 - Concurso de diseñoDesymfony 2012 - Concurso de diseño
Desymfony 2012 - Concurso de diseño
 
Desymfony 2011 - Tutorial #5: Backend
Desymfony 2011 - Tutorial #5: BackendDesymfony 2011 - Tutorial #5: Backend
Desymfony 2011 - Tutorial #5: Backend
 
Desymfony 2011 - Introducción a Symfony2
Desymfony 2011 - Introducción a Symfony2Desymfony 2011 - Introducción a Symfony2
Desymfony 2011 - Introducción a Symfony2
 
Symfony2, Jornadas Symfony
Symfony2, Jornadas SymfonySymfony2, Jornadas Symfony
Symfony2, Jornadas Symfony
 
Curso Symfony - Anexos
Curso Symfony - AnexosCurso Symfony - Anexos
Curso Symfony - Anexos
 
Curso Symfony - Clase 5
Curso Symfony - Clase 5Curso Symfony - Clase 5
Curso Symfony - Clase 5
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4
 
Curso Symfony - Clase 3
Curso Symfony - Clase 3Curso Symfony - Clase 3
Curso Symfony - Clase 3
 
Curso Symfony - Clase 2
Curso Symfony - Clase 2Curso Symfony - Clase 2
Curso Symfony - Clase 2
 
Curso Symfony - Clase 1
Curso Symfony - Clase 1Curso Symfony - Clase 1
Curso Symfony - Clase 1
 

Recently uploaded

redes informaticas en una oficina administrativa
redes informaticas en una oficina administrativaredes informaticas en una oficina administrativa
redes informaticas en una oficina administrativa
nicho110
 

Recently uploaded (12)

pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNIT
 
investigación de los Avances tecnológicos del siglo XXI
investigación de los Avances tecnológicos del siglo XXIinvestigación de los Avances tecnológicos del siglo XXI
investigación de los Avances tecnológicos del siglo XXI
 
Avances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estosAvances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estos
 
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptxEVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
 
How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.
 
redes informaticas en una oficina administrativa
redes informaticas en una oficina administrativaredes informaticas en una oficina administrativa
redes informaticas en una oficina administrativa
 
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptxEL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
 
Buenos_Aires_Meetup_Redis_20240430_.pptx
Buenos_Aires_Meetup_Redis_20240430_.pptxBuenos_Aires_Meetup_Redis_20240430_.pptx
Buenos_Aires_Meetup_Redis_20240430_.pptx
 
Avances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanaAvances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvana
 
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
 
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxPROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
 
Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21
 

Twig avanzado (sf2Vigo)