templating (3/3) | train to symfony

Post on 05-Dec-2014

852 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Topic: Templating in Symfony Language: italian (english version soon) First of three presentations shown during the first edition of the Train to Symfony Verona 13/14 April 2013 http://traintosymfony.com http://twitter.com/TrainToSymfony Emanuele Gaspari https://twitter.com/inmarelibero

TRANSCRIPT

http://traintosymfony.com1 Emanuele Gaspari

TRAINTO SYMFONY

Verona, 13•14 Aprile 2013

the frameworkshop

http://traintosymfony.com@TrainToSymfony

Media partner:

Templating (3/3)

http://traintosymfony.com2 Emanuele Gaspariabout me

creatore di SymfonyBricks

Emanuele Gaspari

ultimo sito pubblicato (copiaincolla): www.ilovesanmartino.it4 bundles21 controllers6 services9 entities5 repositories custom4 estensioni twig14 macros10 bundles aggiuntivi(FOSUserBundle, FOSJsRoutingBundle, KnpPaginatorBundle, CopiaincollaMetaTagsBundle, etc..)

co-sviluppatore di CopiaincollaMetaTagsBundle https://github.com/copiaincolla/MetaTagsBundle

https://symfonybricks.com

inmarelibero@gmail.com @inmarelibero

http://traintosymfony.com3 Emanuele Gaspari

Symfony: teoria e codice

Routing Templating

frameworkshop: il programma

overview

obiettivo della terza parte:

i Templates in Symfony

http://traintosymfony.com4 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com5 Emanuele Gaspariil template engine TWIG

Un template engine (web) è un software progettato per processare un template e dei contenuti, per produrre in output un documento web

Symfony integra il template engine TWIG per il renderingdelle pagine html (e non solo)

http://en.wikipedia.org/wiki/Template_engine_(web)

Train toSymfony6

...posso usare ancora php, come prima?

http://traintosymfony.com7 Emanuele Gaspari

http://traintosymfony.com8 Emanuele Gaspari

se vuoi ancora scrivere codice di questo tipo:

http://traintosymfony.com9 Emanuele Gaspario_O

<html> <head> <title>[...]</title> [...] </head>

<body> <h3>I miei gruppi preferiti</h3> <ul> <?php $info = new BandsManager(true, 12); foreach($bands as $band_name) { $band_info = $info->findInfos($band); echo “<li>”.$band_name; if(!is_null($band_info)) { echo ‘(<a href=”‘.$band_info->site.’”>’.$band_info->site.’</a>)’; } echo “</li>”; } ?> </ul> </body>

</html>

http://traintosymfony.com10 Emanuele Gaspari

http://traintosymfony.com11 Emanuele Gaspariperché un template engine

● separazione tra contenuto (template) e logica (backend, php)● organizzazione del codice secondo il paradigma MVC

perché adottare un template engine, invece che PHP semplice

http://traintosymfony.com12 Emanuele Gasparimmh, non è sufficiente

non sono ancora convinto

http://traintosymfony.com13 Emanuele Gaspari

● flessibile● veloce● sicuro

● blocchi● ereditarietà

● sviluppato da SensioLabs● è abilitato di default in Symfony

perché twig

http://traintosymfony.com14 Emanuele Gasparimmh, non è sufficiente (ancora)

interessante, ma ancora non basta

http://traintosymfony.com15 Emanuele Gaspari

sono due le caratteristiche che fanno preferire TWIG

Train toSymfony16

*non a scapito della potenza

1) semplicità, eleganza

http://traintosymfony.com17 Emanuele Gasparisemplicità, eleganza

<h1>I miei gruppi preferiti</h1>

<ul> {% for band in bands %} <li> {{ band.name }}

{% if band.website %} (<a href=”{{ band.website }}”>official site</a>) {% endif %} </li> {% endfor %}</ul>

Train toSymfony18

*e sono tutti contenti

2) possono metterci le mani sia web designer che sviluppatori

http://traintosymfony.com19 Emanuele Gaspari

http://traintosymfony.com20 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com21 Emanuele GaspariTemplate Naming Pattern

per riferirmi ad un template uso il nome logico, che ha la sintassi:

# src/Tts/DemoBundle/Resources/view/Prodotto/show.html.twig# src/Tts/DemoBundle/Resources/view/Prodotto/show.html.twig

bundle:controller:template

TtsDemoBundle:Prodotto:show.html.twig

Bundle Controller TemplateTtsDemoBundleTtsDemoBundle ProdottoControllerProdottoController show.html.twigshow.html.twig

http://traintosymfony.com22 Emanuele Gaspari

i templates si trovano di default in Resources/views

all'interno le cartelleResources/views/[nome controller]rispecchiano i Controller di un bundle

SymfonyBricksSiteBundle::layout.html.twigSymfonyBricksSiteBundle::layout.html.twig

http://traintosymfony.com23 Emanuele Gasparitip

anche TWIG supporta i namespace(Symfony2)

TtsDemoBundle:Prodotto:show.html.twig

http://symfony.com/doc/current/cookbook/templating/namespaced_paths.html

@TtsDemoBundle/Prodotto/show.html.twig

http://traintosymfony.com24 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com25 Emanuele Gaspari

come Symfony sceglie quale template renderizzare per una certa azione

dalla action al template corretto

http://traintosymfony.com26 Emanuele Gaspari

# src/Tts/DemoBundle/Controller/ProdottoController.php

<?php

class ProdottoController extends Controller{

public function showAction($codice) { $entity = $this->getRepository('TtsDemoBundle:Prodotto')->findOneBy( array(“codice” => $codice) );

return $this->render( 'TtsDemoBundle:Prodotto:show.html.twig', array('entity' => $entity) ); }}

# src/Tts/DemoBundle/Controller/ProdottoController.php

<?php

class ProdottoController extends Controller{

public function showAction($codice) { $entity = $this->getRepository('TtsDemoBundle:Prodotto')->findOneBy( array(“codice” => $codice) );

return $this->render( 'TtsDemoBundle:Prodotto:show.html.twig', array('entity' => $entity) ); }}

# src/Tts/DemoBundle/Resources/view/Prodotto/show.html.twig

$this->render()

la action restituisce un template twig compilato,specificato nella action

http://traintosymfony.com27 Emanuele Gaspari

# src/Tts/DemoBundle/Controller/ProdottoController.php

<?php

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

/** * @Template() */public function showAction($codice){ $entity = $this->getRepository('TtsDemoBundle:Prodotto')->findOneBy( array(“codice” => $codice) ); return array(“entity” => $entity);}

# src/Tts/DemoBundle/Controller/ProdottoController.php

<?php

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

/** * @Template() */public function showAction($codice){ $entity = $this->getRepository('TtsDemoBundle:Prodotto')->findOneBy( array(“codice” => $codice) ); return array(“entity” => $entity);}

# src/Tts/DemoBundle/Resources/view/Prodotto/show.html.twig

sfrutto l'annotazione @Template()

@Template()

http://traintosymfony.com28 Emanuele Gaspari

# src/Tts/DemoBundle/Controller/ProdottoController.php

<?php

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

/** * @Template(“TtsDemoBundle:Prodotto:show_offerta.html.twig”) */public function showAction($codice){

[…] return array(“entity” => $entity);}

# src/Tts/DemoBundle/Controller/ProdottoController.php

<?php

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

/** * @Template(“TtsDemoBundle:Prodotto:show_offerta.html.twig”) */public function showAction($codice){

[…] return array(“entity” => $entity);}

# src/Tts/DemoBundle/Resources/view/Prodotto/show_offerta.html.twig

utilizzo l'annotazione @Template() specificando un parametro

@Template(...)

http://traintosymfony.com29 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com30 Emanuele Gasparisintassi

sintassi speciale di TWIG

{{ ... }}“dire” qualcosa

{% ... %}“fare” qualcosa

http://traintosymfony.com31 Emanuele Gasparivariabili

{{ prodotto['codice'] }}{{ prodotto['codice'] }}

{{ nomeProdotto }}{{ nomeProdotto }}

{{ ... }} stampa il contenuto di una variabile

nomeProdotto è una stringa

prodotto è un array associativo

{{ prodotto.codice }}{{ prodotto.codice }}

prodotto potrebbe essere un array o un oggetto

http://traintosymfony.com32 Emanuele Gasparioperatore .

l'operatore . si comporta diversamente in base alla variabile

● prodotto è un array e codice una chiave● prodotto è un oggetto e codice una proprietà accessibile● prodotto è un oggetto e codice() un metodo accessibile● prodotto è un oggetto e getCodice() un metodo accessibile● prodotto è un oggetto e isCodice() un metodo accessibile

{{ prodotto.codice }}{{ prodotto.codice }}

verifica se:

http://traintosymfony.com33 Emanuele Gasparidichiarare una variabile

{% set nomeProdotto = 'Chiave inglese' %}{% set nomeProdotto = 'Chiave inglese' %}

{% set ... %} permette di inizializzare variabili all'interno del template TWIG

{% set nomeProdottoEsteso = nomeProdotto ~ “ (Attrezzi da lavoro)” %}{% set nomeProdottoEsteso = nomeProdotto ~ “ (Attrezzi da lavoro)” %}

concatenazione di stringhe

{% set misureDisponibili = [12, 24, 36] %}{% set misureDisponibili = [12, 24, 36] %}

{% set misureDisponibiliQuantita = {'12': 128, '24': 2, '36': 74} %}{% set misureDisponibiliQuantita = {'12': 128, '24': 2, '36': 74} %}

http://traintosymfony.com34 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com35 Emanuele Gasparifiltri

{{ nomeProdotto | upper }}{{ nomeProdotto | upper }}

le variabili posso essere modificate dai filtri

i filtri si applicano alla variabile separandoli con |,e possono accettare dei parametri

{{ misureDisponibili | join(“, ”) }}{{ misureDisponibili | join(“, ”) }}

http://twig.sensiolabs.org/doc/filters/index.html

http://traintosymfony.com36 Emanuele Gasparifiltri più comuni

{{ catalogo.ultimoAggiornamento | date(“m/d/Y”) }}{{ catalogo.ultimoAggiornamento | date(“m/d/Y”) }}

{{ misureDisponibili | join(“, ”) }}{{ misureDisponibili | join(“, ”) }}

{% if misureDisponibili | length > 0 %}...

{% endif %}

{% if misureDisponibili | length > 0 %}...

{% endif %}

{{ prodotto.descrizioneEstesa | nl2br }}{{ prodotto.descrizioneEstesa | nl2br }} {{ prodotto.descrizioneEstesa | raw }}{{ prodotto.descrizioneEstesa | raw }}

{% for i in misureDisponibili | slice(1, 5) %}...

{% endfor %}

{% for i in misureDisponibili | slice(1, 5) %}...

{% endfor %}

http://traintosymfony.com37 Emanuele Gaspariconcatenazione

{{ misureDisponibili | slice(1, 5) | join(separator) }}{{ misureDisponibili | slice(1, 5) | join(separator) }}

{{ prodotto.descrizioneEstesa | nl2br | raw }}{{ prodotto.descrizioneEstesa | nl2br | raw }}

i filtri possono essere concatenati

http://traintosymfony.com38 Emanuele Gasparifunzioni

le funzioni generano contenuto

si possono utilizzare sia all'interno di {{ ... }} che di {% ... %}

{% for i in range(1, 100) %}{% for i in range(1, 100) %}

{{ random(100) }}{{ random(100) }}

http://twig.sensiolabs.org/doc/functions/index.html

http://traintosymfony.com39 Emanuele Gasparifunzioni comuni

{{ dump(misureDisponibili) }}{{ dump(misureDisponibili) }}

{{ include(template_from_string("Codice prodotto: {{ prodotto.codice }}") }}{{ include(template_from_string("Codice prodotto: {{ prodotto.codice }}") }}

{{ random(['red', 'blue', 'yellow']) }}{{ random(['red', 'blue', 'yellow']) }}

{% for i in range(0, 3) %}...

{% endfor %}

{% for i in range(0, 3) %}...

{% endfor %}

http://traintosymfony.com40 Emanuele Gasparicombinazione di funzioni

{% for i in range( random(100) ) %}{% for i in range( random(100) ) %}

le funzioni possono essere utilizzate insieme

http://traintosymfony.com41 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com42 Emanuele Gasparistrutture di controllo

gli operatori per le strutture di controllo in TWIG sono detti tag

{% if misureDisponibili | length > 0 %}<ul>

{% for misura, quantita in misureDisponibiliQuantita %} <li>

{{ quantita }} pezzi sono disponibiliper la misura “{{ misura }}”

</li> {% endfor %} </ul>{% else %}

Spiacenti, questo articolo non è disponibile in alcuna misura{% endif %}

{% if misureDisponibili | length > 0 %}<ul>

{% for misura, quantita in misureDisponibiliQuantita %} <li>

{{ quantita }} pezzi sono disponibiliper la misura “{{ misura }}”

</li> {% endfor %} </ul>{% else %}

Spiacenti, questo articolo non è disponibile in alcuna misura{% endif %}

http://twig.sensiolabs.org/doc/tags/index.html

http://traintosymfony.com43 Emanuele Gasparistrutture di controllo

i tag possono anche effettuare delle operazioni sul loro contenuto

{% filter lower | capitalize %} {{ prodotto.descrizione }}{% endfilter %}

{% filter lower | capitalize %} {{ prodotto.descrizione }}{% endfilter %}

{% macro printDescrizioneProdotto(prodotto) %} Descrizione prodotto: {{ prodotto.codice }} - {{ prodotto.descrizione | raw }}{% endmacro %}

{{ _self.printDescrizioneProdotto(entity) }}

{% macro printDescrizioneProdotto(prodotto) %} Descrizione prodotto: {{ prodotto.codice }} - {{ prodotto.descrizione | raw }}{% endmacro %}

{{ _self.printDescrizioneProdotto(entity) }}

{% spaceless %} <div> <strong>foo</strong> </div>{% endspaceless %}

{% spaceless %} <div> <strong>foo</strong> </div>{% endspaceless %}

http://traintosymfony.com44 Emanuele Gasparicombinazione di tags

i tags possono essere utilizzati insieme

{% macro printDescrizioneProdotto(prodotto) %} Descrizione prodotto: {{ prodotto.codice }} -

{% filter lower | capitalize %}{{ prodotto.descrizione | raw }}

{% endfilter %}{% endmacro %}

{% spaceless %}{{ _self.printDescrizioneProdotto(entity) }}

{% endspaceless %}

{% macro printDescrizioneProdotto(prodotto) %} Descrizione prodotto: {{ prodotto.codice }} -

{% filter lower | capitalize %}{{ prodotto.descrizione | raw }}

{% endfilter %}{% endmacro %}

{% spaceless %}{{ _self.printDescrizioneProdotto(entity) }}

{% endspaceless %}

http://traintosymfony.com45 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com46 Emanuele Gaspariconfronti e test

TWIG offre una sintassi semplice per effettuare confronti e test

http://traintosymfony.com47 Emanuele Gasparioperatori di confronto

operatori di confronto

{% if prodotto.codice == '127' %}{% if prodotto.codice == '127' %}

== != < > >= <=== != < > >= <=

{% if misureDisponibili | length > 0 %}{% if misureDisponibili | length > 0 %}

http://traintosymfony.com48 Emanuele Gasparioperatore test

l'operatore is effettua dei test su una variabile

{% if loop.index is divisibleby(3) %}{% if loop.index is divisibleby(3) %}

{% if loop.index is even %}{% if loop.index is even %}

http://twig.sensiolabs.org/doc/tests/index.html

{% if loop.index is not divisibleby(3) %}{% if loop.index is not divisibleby(3) %}

http://traintosymfony.com49 Emanuele Gasparioperatore ternario

come in PHP, anche in TWIG esiste un operatore ternario

{% for misura in misureDisponibili %}<tr class=”{{ ( loop.index is even ) ? “even” : “odd” }}”>[...]

{% endfor %}

{% for misura in misureDisponibili %}<tr class=”{{ ( loop.index is even ) ? “even” : “odd” }}”>[...]

{% endfor %}

http://twig.sensiolabs.org/doc/tests/index.html

http://traintosymfony.com50 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com51 Emanuele Gaspariereditarietà di templates

la killer feature di TWIG è il meccanismo di ereditarietà di templates

in ogni template è possibile definire dei blocchiil cui contenuto può essere sovrascritto

un template può estendere un altro templateper sfruttare le parti comuni e

sovrascriverne altre

http://traintosymfony.com52 Emanuele Gaspariereditarietà di templates

# src/Tts/DemoBundle/Resources/views/layout.html.twig

<!DOCTYPE html><html>

<head><title>{% block title %}workshop{% endblock %} | Train to Symfony</title>

</head> <body>

<div id="main">{% block main %}{% endblock %}

</div> <div id="footer"> {% block footer %}

Train to Symfony - Verona, 13•14 Aprile 2013 {% endblock %} </div> </body></html>

# src/Tts/DemoBundle/Resources/views/layout.html.twig

<!DOCTYPE html><html>

<head><title>{% block title %}workshop{% endblock %} | Train to Symfony</title>

</head> <body>

<div id="main">{% block main %}{% endblock %}

</div> <div id="footer"> {% block footer %}

Train to Symfony - Verona, 13•14 Aprile 2013 {% endblock %} </div> </body></html>

definisco un template di base (es. layout), che imposta la struttura generale

http://traintosymfony.com53 Emanuele Gaspariereditarietà di templates

# src/Tts/DemoBundle/Resources/views/Default/about.html.twig

{% extends "TtsDemoBundle::layout.html.twig" %}

{% block title %}about{% endblock %}

{% block main %} <h1>Train to Symfony</h1> <p>

Train to Symfony è un puntualissimo convoglio che ti offre un corsofortemente pratico su questo sempre più utilizzato framework.

</p>{% endblock %}

# src/Tts/DemoBundle/Resources/views/Default/about.html.twig

{% extends "TtsDemoBundle::layout.html.twig" %}

{% block title %}about{% endblock %}

{% block main %} <h1>Train to Symfony</h1> <p>

Train to Symfony è un puntualissimo convoglio che ti offre un corsofortemente pratico su questo sempre più utilizzato framework.

</p>{% endblock %}

creo un template che lo estende, e sovrascrivo solo i blocchi che mi servono

http://traintosymfony.com54 Emanuele Gaspariereditarietà di templates

<!DOCTYPE html><html>

<head><title>about | Train to Symfony</title>

</head> <body>

<div id="main"> <h1>Train to Symfony</h1>

<p>Train to Symfony è un puntualissimo convoglio che ti offre un corsofortemente pratico su questo sempre più utilizzato framework.

</p></div>

<div id="footer">Train to Symfony - Verona, 13•14 Aprile 2013

</div> </body></html>

<!DOCTYPE html><html>

<head><title>about | Train to Symfony</title>

</head> <body>

<div id="main"> <h1>Train to Symfony</h1>

<p>Train to Symfony è un puntualissimo convoglio che ti offre un corsofortemente pratico su questo sempre più utilizzato framework.

</p></div>

<div id="footer">Train to Symfony - Verona, 13•14 Aprile 2013

</div> </body></html>

il risultato è la combinazione tra layout.html.twige i blocchi che sono stati sovrascritti

http://traintosymfony.com55 Emanuele Gaspariregole

ogni template può estendere al massimo un template

ogni template può essere esteso da un altro template

l'ereditarietà si concatena

http://traintosymfony.com56 Emanuele Gasparitag {% extends %}

il tag {% extends %} è flessibile

{% extends (mobile_layout) ? "layout_mobile.html.twig" : "layout.html.twig" %}{% extends (mobile_layout) ? "layout_mobile.html.twig" : "layout.html.twig" %}

{% extends custom_layout %}{% extends custom_layout %}

{% extends [custom_layout, mobile_layout] %}{% extends [custom_layout, mobile_layout] %}

{% extends "TtsDemoBundle::layout.html.twig" %}{% extends "TtsDemoBundle::layout.html.twig" %}

http://traintosymfony.com57 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com58 Emanuele Gasparimacro

# src/Tts/DemoBundle/Resources/views/Default/index.html.twig

{% import "TtsDemoBundle::macros/macrosProdotto.html.twig" as macrosProdotto %}

{% for entity in entities %}{{ macroProdotto.printDescrizione(entity) }}

{% endfor %}

# src/Tts/DemoBundle/Resources/views/Default/index.html.twig

{% import "TtsDemoBundle::macros/macrosProdotto.html.twig" as macrosProdotto %}

{% for entity in entities %}{{ macroProdotto.printDescrizione(entity) }}

{% endfor %}

# src/Tts/DemoBundle/Resources/views/macros/macrosProdotto.html.twig

{% macro printDescrizione(prodotto) %}<div> Descrizione prodotto: {{ prodotto.codice }} - {{ prodotto.descrizione | raw }}</div>

{% endmacro %}

# src/Tts/DemoBundle/Resources/views/macros/macrosProdotto.html.twig

{% macro printDescrizione(prodotto) %}<div> Descrizione prodotto: {{ prodotto.codice }} - {{ prodotto.descrizione | raw }}</div>

{% endmacro %}

una macro è una porzione di codice TWIG riutilizzabile

http://traintosymfony.com59 Emanuele Gaspari

Templating

template engine

Template Naming Pattern

dalla action al template

TWIG

sintassi e variabili

filtri e funzioni

strutture di controllo

comparazioni e test

ereditarietà

macro

variabili globali

TEMPLATING

http://traintosymfony.com60 Emanuele Gasparivariabili globali

in ogni template si posso utilizzare delle variabili globalimesse a disposizione da Symfony

app.security security context.app.user oggetto User correnteapp.request oggetto Requestapp.session oggetto Sessionapp.environment environment corrent (dev, prod)app.debug true se in modalità debug

app.security security context.app.user oggetto User correnteapp.request oggetto Requestapp.session oggetto Sessionapp.environment environment corrent (dev, prod)app.debug true se in modalità debug

http://traintosymfony.com61 Emanuele Gasparivariabili globali custom

è anche possibile specificare una variabile nei file di configurazione,e utilizzarla in qualsiasi template TWIG

{{ available_locales | join(“, ”) }}{{ available_locales | join(“, ”) }}

# app/config/config.yml

parameters:available_locales: [it, en]

twig:globals:

available_locales: %available_locales%

# app/config/config.yml

parameters:available_locales: [it, en]

twig:globals:

available_locales: %available_locales%

TRAINTO SYMFONY

Verona, 13•14 Aprile 2013

the frameworkshop

http://traintosymfony.com@TrainToSymfony

Media partner:©Copyright Emanuele Gaspari Castelletti

top related