Download - Routing (2/3) | Train to Symfony
http://traintosymfony.com1 Emanuele Gaspari
TRAINTO SYMFONY
Verona, 13•14 Aprile 2013
the frameworkshop
http://traintosymfony.com@TrainToSymfony
Media partner:
Routing (2/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
[email protected] @inmarelibero
http://traintosymfony.com3 Emanuele Gaspari
Symfony: teoria e codice
Routing Templating
frameworkshop: il programma
overview
obiettivo della seconda parte:
il sistema di Routing in Symfony
http://traintosymfony.com4 Emanuele GaspariRouting
il Routing è il meccanismo di associazione tra url e controllers
http://traintosymfony.com5 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com6 Emanuele GaspariController
Symfony\Bundle\FrameworkBundle\Controller\Controller
● riceve i parametri● esegue delle operazioni e restituisce una risposta
in Symfony un Controller è una classe PHP che estende la classe
task comuni: passaggio di variabili ai templates, accesso a “servizi”, comunicazione con database, redirect
http://traintosymfony.com7 Emanuele Gaspari
● funzione definita all'interno di un controller
● la firma ha la sintassi public function ...Action()
nel Controller vengono definite le
actions (azioni)
Action
http://traintosymfony.com8 Emanuele Gaspariactions: esempi
# src/Tts/DemoBundle/Controller/DefaultController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller{
public function homepageAction() { [...] }
public function contattiAction() { [...] }
public function chiSiamoAction() { [...] }}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller{
public function homepageAction() { [...] }
public function contattiAction() { [...] }
public function chiSiamoAction() { [...] }}
http://traintosymfony.com9 Emanuele Gaspariscopo di un'azione
lo scopo di un'azione è di preparare i datiche verranno mostrati nel template
le azioni non dovrebbero essere molto estese
se un'azione lo è, chiediti se la logica debba essereridistribuita in altri servizi, repository, entities
http://traintosymfony.com10 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com11 Emanuele Gaspari
una Route è un'associazione tra url e controller che specifico:
Route: tra url e Controller
● in app/config/routing.yml● in un altro file yml● nel controller
http://traintosymfony.com12 Emanuele Gaspari
# app/config/routing.yml
homepage: path: / defaults: { _controller: TtsDemoBundle:Default:homepage }
# app/config/routing.yml
homepage: path: / defaults: { _controller: TtsDemoBundle:Default:homepage }
# src/Tts/DemoBundle/Controller/DefaultController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller{
public function homepageAction() { return $this->render( 'TtsDemoBundle:Default:homepage.html.twig' );
}}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller{
public function homepageAction() { return $this->render( 'TtsDemoBundle:Default:homepage.html.twig' );
}}
/
http://traintosymfony.com13 Emanuele Gaspari
# app/config/routing.yml
index_catalogo: path: /catalogo defaults: { _controller: TtsDemoBundle:Catalogo:index }
# app/config/routing.yml
index_catalogo: path: /catalogo defaults: { _controller: TtsDemoBundle:Catalogo:index }
# src/Tts/DemoBundle/Controller/CatalogoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class CatalogoController extends Controller{
public function indexAction(){
[...] }}
# src/Tts/DemoBundle/Controller/CatalogoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class CatalogoController extends Controller{
public function indexAction(){
[...] }}
/catalogo
http://traintosymfony.com14 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com15 Emanuele Gaspari
stabilisco che una parte del path è variabile
Routes {parametriche}
le parti variabili sono comprese tra { } e vengono passateall'azione come argomenti
http://traintosymfony.com16 Emanuele Gaspari
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Smfony\Bundle\FrameworkBundle\Controller\Controller;
class ProdottoController extends Controller{
public function showAction($codice){
$em = $this->getDoctrine()->getManager();$entity = $em->getRepository('TtsDemoBundle:Prodotto')->find($codice);[...]
}}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Smfony\Bundle\FrameworkBundle\Controller\Controller;
class ProdottoController extends Controller{
public function showAction($codice){
$em = $this->getDoctrine()->getManager();$entity = $em->getRepository('TtsDemoBundle:Prodotto')->find($codice);[...]
}}
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} defaults: { _controller: TtsDemoBundle:Prodotto:show }
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} defaults: { _controller: TtsDemoBundle:Prodotto:show }
/prodotto/{codice}
http://traintosymfony.com17 Emanuele Gaspari
# app/config/routing.yml
prodotto_show: path: /prodotto/{categoria}/{codice}/{slug} defaults: { _controller: TtsDemoBundle:Prodotto:show }
# app/config/routing.yml
prodotto_show: path: /prodotto/{categoria}/{codice}/{slug} defaults: { _controller: TtsDemoBundle:Prodotto:show }
/prodotto/{categoria}/{codice}/{slug}
http://traintosymfony.com18 Emanuele Gaspari
GET /prodotto/147?mobile_layout=trueGET /prodotto/147?mobile_layout=true
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} defaults: { _controller: TtsDemoBundle:Prodotto:show }
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} defaults: { _controller: TtsDemoBundle:Prodotto:show }
<?php
public function showAction($codice){ $request = $this->getRequest(); $mobileLayout = $request->get('mobile_layout');
// oppure, più estesamente $mobileLayout = $request->query->get('mobile_layout', 'false');
[…]}
<?php
public function showAction($codice){ $request = $this->getRequest(); $mobileLayout = $request->get('mobile_layout');
// oppure, più estesamente $mobileLayout = $request->query->get('mobile_layout', 'false');
[…]}
passaggio di parametri $_GET
http://traintosymfony.com19 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com20 Emanuele Gaspari
al posto di definire una Route per ogni (sintassi di) url in un file yml
posso usare l'annotazione @Route direttamente nel controller
http://traintosymfony.com21 Emanuele Gaspari
=
# src/Tts/DemoBundle/Controller/DefaultController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class DefaultController extends Controller{
/** * @Route("/", name=”homepage”) */ public function homepageAction() { [...] }}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class DefaultController extends Controller{
/** * @Route("/", name=”homepage”) */ public function homepageAction() { [...] }}
# app/config/routing.yml
homepage: path: / defaults: { _controller: TtsDemoBundle:Default:homepage }
http://traintosymfony.com22 Emanuele Gaspari
# app/config/routing.yml
index_catalogo: path: /catalogo defaults: { _controller: TtsDemoBundle:Catalogo:index }
# src/Tts/DemoBundle/Controller/CatalogoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class CatalogoController extends Controller{ /** * @Route("/catalogo", name=”index_catalogo”) */ public function indexAction() { [...] }}
# src/Tts/DemoBundle/Controller/CatalogoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class CatalogoController extends Controller{ /** * @Route("/catalogo", name=”index_catalogo”) */ public function indexAction() { [...] }}
=
http://traintosymfony.com23 Emanuele Gaspari
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} defaults: { _controller: TtsDemoBundle:Prodotto:show }
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ProdottoController extends Controller{ /** * @Route("/prodotto/{codice}", name=”prodotto_show”) */ public function showAction($codice) { [...] }}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ProdottoController extends Controller{ /** * @Route("/prodotto/{codice}", name=”prodotto_show”) */ public function showAction($codice) { [...] }}
=
http://traintosymfony.com24 Emanuele Gaspari
# app/config/routing.yml
prodotto_show: path: /prodotto/{categoria}/{codice}/{slug} defaults: { _controller: TtsDemoBundle:Prodotto:show }
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ProdottoController extends Controller{ /** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */ public function showAction($categoria, $codice, $slug) { [...] }}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ProdottoController extends Controller{ /** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */ public function showAction($categoria, $codice, $slug) { [...] }}
=
http://traintosymfony.com25 Emanuele Gaspari
definisco in app/config/routing.yml quali controller caricare
http://traintosymfony.com26 Emanuele Gasparitype: annotation
# app/config/config.yml
# TtsDemoBundle Default controllerdefault: resource: “@TtsDemoBundle/Controller/DefaultController.php” type: annotation
# TtsDemoBundle Catalogo controllercatalogo: resource: “@TtsDemoBundle/Controller/CatalogoController.php” type: annotation
# TtsDemoBundle Prodotto controllerprodotto: resource: “@TtsDemoBundle/Controller/ProdottoController.php” type: annotation
# app/config/config.yml
# TtsDemoBundle Default controllerdefault: resource: “@TtsDemoBundle/Controller/DefaultController.php” type: annotation
# TtsDemoBundle Catalogo controllercatalogo: resource: “@TtsDemoBundle/Controller/CatalogoController.php” type: annotation
# TtsDemoBundle Prodotto controllerprodotto: resource: “@TtsDemoBundle/Controller/ProdottoController.php” type: annotation
http://traintosymfony.com27 Emanuele Gasparitype: annotation (2)
# app/config/config.yml
# TtsDemoBundletts_demo: resource: “@TtsDemoBundle/Controller/” type: annotation
# app/config/config.yml
# TtsDemoBundletts_demo: resource: “@TtsDemoBundle/Controller/” type: annotation
o, semplicemente, specifico la cartella che li contiene tutti
http://traintosymfony.com28 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com29 Emanuele Gaspari
best practice
far corrispondere ad ogni url una sola route
http://traintosymfony.com30 Emanuele Gaspari
GET /prodotto/EG-124 => prodotto_showGET /prodotto/index => prodotto_show, prodotto_index
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} defaults: { _controller: TtsDemoBundle:Prodotto:show }
prodotto_index: path: /prodotto/index defaults: { _controller: TtsDemoBundle:Prodotto:index }
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} defaults: { _controller: TtsDemoBundle:Prodotto:show }
prodotto_index: path: /prodotto/index defaults: { _controller: TtsDemoBundle:Prodotto:index }
collisione di urls
http://traintosymfony.com31 Emanuele Gaspari
sfrutto l'ordine con cui vengono definite le Routes
il controller si ferma alla prima Route abbinata all'url
è sufficiente definire prima la Route che non contiene parametri
GET /prodotto/indexGET /prodotto/EG-124
# app/config/routing.yml
prodotto_index: path: /prodotto/index
prodotto_show: path: /prodotto/{codice}
# app/config/routing.yml
prodotto_index: path: /prodotto/index
prodotto_show: path: /prodotto/{codice}
soluzione 1, ordine delle Routes
http://traintosymfony.com32 Emanuele Gaspari
rimane ancora il problema della collisione di urls verso più di una Route
basarsi sull'ordine con cui vengono esaminate le Routes non è sufficiente:dopo un anno che il sito è in produzione, mi ricordo che la
posizione di quella specifica Route è vitale?
anche usando l'annotazione @Route, posso non volere cheall'interno di un Controller una funzione venga spostata
in alto solo perché la Route venga esaminata prima
l'ordine non basta
http://traintosymfony.com33 Emanuele Gaspari
sfrutto il parametro requirements
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} requirements: codice: [A-Z]{2}-[0-9]+
prodotto_index: path: /prodotto/index
# app/config/routing.yml
prodotto_show: path: /prodotto/{codice} requirements: codice: [A-Z]{2}-[0-9]+
prodotto_index: path: /prodotto/index
GET /prodotto/indexGET /prodotto/EG-124
non c'è più collisione tra Routesnon mi affido più all'ordine di caricamento
soluzione 2, parametro requirements
pongo dei vincoli sul formato di un parametro di una Route
http://traintosymfony.com34 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com35 Emanuele Gaspari
Symfony associa il nome logico ad unaspecifica classe e metodo (Controller e Action)
bundle:controller:action
nome logico di un Controllersintassi per riferirsi ad un'azione da qualunque punto dell'applicazione
Controller Naming Pattern
http://traintosymfony.com36 Emanuele Gaspari
TtsDemoBundle:Default:homepage
Bundle Controller MetodoTtsDemoBundleTtsDemoBundle DefaultControllerDefaultController homepageAction()homepageAction()
# src/Tts/DemoBundle/Controller/DefaultController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller{
public function homepageAction() { […] }}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?phpnamespace Tts\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller{
public function homepageAction() { […] }}
Controller Naming Pattern
http://traintosymfony.com37 Emanuele Gaspari
# template twig
{{ render(controller(“TtsDemoBundle:Blog:latestPosts”, {“max”: 5})) }}
# template twig
{{ render(controller(“TtsDemoBundle:Blog:latestPosts”, {“max”: 5})) }}
esempio
http://traintosymfony.com38 Emanuele Gaspari
$ php app/console router:debug$ php app/console router:debug
$ php app/console router:match /prodotto/EG-124$ php app/console router:match /prodotto/EG-124
tips
stampare a console l'elenco di tutte le Routes caricate
verificare se un path è associato da Symfony ad una Route
http://traintosymfony.com39 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com40 Emanuele Gasparioggetto Request
Symfony\Component\HttpFoundation\Request
oggetto che ho a disposizione all'interno di ogni azioneper gestire tutti i parametri della richiesta
Symfony utilizza un oggetto Request per modellare una richiesta HTTP
http://traintosymfony.com41 Emanuele Gaspariaccedere ad un oggetto Request
<?php
public function homepageAction(){
$request = $this->getRequest();}
<?php
public function homepageAction(){
$request = $this->getRequest();}
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
accedere a Request in una Action:
accedere a Request da qualunque punto dell'applicazione (in PHP):
$this->getRequest() => 0.04 KbRequest::createFromGlobals() => 7.07 Kb
{{ app.request }}{{ app.request }}
accedere a Request da twig:
http://traintosymfony.com42 Emanuele Gasparipanoramica
$_GET$request->query
$_POST$request->request
$_COOKIE$request->cookies
$_FILE$request->files
$_SERVER$request->server
http://api.symfony.com/master/Symfony/Component/HttpFoundation/Request.html
$request
->getPathInfo() ->getMethod() ->getLanguages()
->getRequestUri() ->getClientIp() ->getPreferredLanguage()
->getScriptName() ->getSession() ->isXmlHttpRequest()
http://traintosymfony.com43 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com44 Emanuele Gaspari
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug, $categoria){ [...]}
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug, $categoria){ [...]}
url con parametri
200 GET /prodotto/nuovi/EG-124/eg-124-new-hammer
non importa l'ordinepossono non essere specificati tutti
l'ordine è importante, per associare i parametri dell'url
404 GET /prodotto/nuovi/EG-124404 GET /prodotto/nuovi/EG-124/
http://traintosymfony.com45 Emanuele Gasparidefaults (1)
200 GET /prodotto/nuovi/EG-124/eg-124-new-hammer200 GET /prodotto/nuovi/EG-124
404 GET /prodotto/nuovi/EG-124/
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”, defaults={“slug”: “-”}) */public function showAction($codice, $categoria, $slug) { [...] }
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”, defaults={“slug”: “-”}) */public function showAction($codice, $categoria) { [...] }
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $categoria, $slug = “-”) { [...] }
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”, defaults={“slug”: “-”}) */public function showAction($codice, $categoria, $slug) { [...] }
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”, defaults={“slug”: “-”}) */public function showAction($codice, $categoria) { [...] }
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $categoria, $slug = “-”) { [...] }
http://traintosymfony.com46 Emanuele Gaspariaccesso ai parametri
200 GET /prodotto/nuovi/EG-124/eg-124-new-hammer?color=red200 GET /prodotto/nuovi/EG-124?color=red
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug = “-”, $categoria){
$request = $this->getRequest();
// nell'url $codice; $codice = $request->get(“codice”);
// in $_GET $color = $request->get(“color”); $color = $request->query->get(“color”);
[...]}
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug = “-”, $categoria){
$request = $this->getRequest();
// nell'url $codice; $codice = $request->get(“codice”);
// in $_GET $color = $request->get(“color”); $color = $request->query->get(“color”);
[...]}
http://traintosymfony.com47 Emanuele Gaspari?get= o /{param}
● parametro essenziale?● eleganza degli url● cambio successivo degli url● indicizzazione dei motori di ricerca● multilingua
quando passare un parametro come ?get=
e quando come/{param}
http://traintosymfony.com48 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com49 Emanuele GaspariResponse
ogni Action restituisce sempre un oggetto Response
real life: molte volte la Action che implementerai restituiràsemplicemente un array di variabili, utilizzabili
in un template che viene scelto più o meno “automaticamente”
http://traintosymfony.com50 Emanuele Gasparireturn array
la situazione più semplice è quella in cui utilizzol'annotation @Template e la mia Action restituisce
semplicemente un array
http://traintosymfony.com51 Emanuele Gasparireturn array
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class ProdottoController extends Controller{ /** * @Route(“/prodotto/{categoria}/{codice}/{slug}”, name=”prodotto_show”) * @Template() */ public function showAction($codice, $slug, $categoria) {
$entity = $this->getRepository('TtsDemoBundle:Prodotto')->findOneBy( array(“codice” => $codice) );
return array('entity' => $entity); }
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class ProdottoController extends Controller{ /** * @Route(“/prodotto/{categoria}/{codice}/{slug}”, name=”prodotto_show”) * @Template() */ public function showAction($codice, $slug, $categoria) {
$entity = $this->getRepository('TtsDemoBundle:Prodotto')->findOneBy( array(“codice” => $codice) );
return array('entity' => $entity); }
http://traintosymfony.com52 Emanuele Gasparirender()
posso fare in modo che l'azione restituisca un template TWIG compilato,ad esempio perché è diverso in base alla logica interna dell'azione
utlizzo la funzione $this->render() specificando il template
http://traintosymfony.com53 Emanuele Gaspari
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
class ProdottoController extends Controller{
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug, $categoria){ $entity = $this->getRepository('TtsDemoBundle:Prodotto')->findOneBy(
array(“codice” => $codice) );
return $this->render('TtsDemoBundle:Prodotto:show_offer.html.twig', array('entity' => $entity
));}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
class ProdottoController extends Controller{
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug, $categoria){ $entity = $this->getRepository('TtsDemoBundle:Prodotto')->findOneBy(
array(“codice” => $codice) );
return $this->render('TtsDemoBundle:Prodotto:show_offer.html.twig', array('entity' => $entity
));}
$this->render()
http://traintosymfony.com54 Emanuele Gasparicostruire una Response
è possibile anche costruire un oggetto Response
utile nel caso in cui abbia necessità di costruire la rispostain più passaggi a seconda di variabili
o di effettuare delle operazioni successivamente
http://traintosymfony.com55 Emanuele Gasparicostruire una Response
utilizzo la funzione $this->renderView() per memorizzareun contenuto HTML in una variabile
creo un oggetto Response con quella variabile come primo argomentoimpostando
http://traintosymfony.com56 Emanuele Gaspari
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use Symfony\Component\HttpFoundation\Response;
class ProdottoController extends Controller{
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug, $categoria){ $entity = [...]
$content = $this->renderView('TtsDemoBundle:Prodotto:show.html.twig', array('entity' => $entity
));
[...]
return new Response($content);}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use Symfony\Component\HttpFoundation\Response;
class ProdottoController extends Controller{
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug, $categoria){ $entity = [...]
$content = $this->renderView('TtsDemoBundle:Prodotto:show.html.twig', array('entity' => $entity
));
[...]
return new Response($content);}
http://traintosymfony.com57 Emanuele Gaspari
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use Symfony\Component\HttpFoundation\Response;
class ProdottoController extends Controller{
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug, $categoria){ $entity = [...]
$response = new Response($entity->getCodice(), 200, array('content-type' => 'text/html'
));
$response->prepare($this->getRequest());$response->send();
}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use Symfony\Component\HttpFoundation\Response;
class ProdottoController extends Controller{
/** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */public function showAction($codice, $slug, $categoria){ $entity = [...]
$response = new Response($entity->getCodice(), 200, array('content-type' => 'text/html'
));
$response->prepare($this->getRequest());$response->send();
}
http://traintosymfony.com58 Emanuele Gasparijson
anche restituire una risposta in formato json è semplice
http://traintosymfony.com59 Emanuele Gasparijson Response
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use Symfony\Component\HttpFoundation\Response;use Symfony\Component\HttpFoundation\JsonResponse;
public function jsonAction($codice, $slug, $categoria){ $entity = [...]
$jsonResponse = array(“codice” => $entity->getCodice(), [...]);
// crea una risposta JSON$response = new Response(json_encode($jsonResponse));$response->headers->set('Content-Type', 'application/json');return $response;
// crea una risposta JSON utilizzando la classe JsonResponse (Symfony >= 2.1)$response = new JsonResponse();$response->setData($jsonResponse);return $response;
}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use Symfony\Component\HttpFoundation\Response;use Symfony\Component\HttpFoundation\JsonResponse;
public function jsonAction($codice, $slug, $categoria){ $entity = [...]
$jsonResponse = array(“codice” => $entity->getCodice(), [...]);
// crea una risposta JSON$response = new Response(json_encode($jsonResponse));$response->headers->set('Content-Type', 'application/json');return $response;
// crea una risposta JSON utilizzando la classe JsonResponse (Symfony >= 2.1)$response = new JsonResponse();$response->setData($jsonResponse);return $response;
}
http://traintosymfony.com60 Emanuele Gaspaririassunto
● un array● $this->render()● $this->renderView()● un oggetto Response● un oggetto JsonResponse
abbiamo visto che un'azione può utilizzare:
...e può fare molto altro!
http://traintosymfony.com61 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com62 Emanuele Gaspariredirect
il redirect è un messaggio al browsercambia l'url perché è effettivamente una nuova richiesta
in caso di:● redirect temporaneo (302, default) o permanente (301)● invio corretto di un form: redirezione ad una pagina di conferma● se il sito è multilingua, si può effettuare un redirect dopo aver scelto la lingua
in base al browser
http://traintosymfony.com63 Emanuele Gaspariredirect temporaneo
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
class DefaultController extends Controller{
/** * @Route("/", name=”homepage”)
*/public function homepageAction(){
return $this->redirect($this->generateUrl('homepage_natale'));}
}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
class DefaultController extends Controller{
/** * @Route("/", name=”homepage”)
*/public function homepageAction(){
return $this->redirect($this->generateUrl('homepage_natale'));}
}
redirect temporaneo ad un altro url
http://traintosymfony.com64 Emanuele GaspariRedirectResponse
c'è un oggetto dedicato (che sorpresa!) che la Action può restituire in caso di redirect: RedirectResponse
http://traintosymfony.com65 Emanuele GaspariRedirectResponse
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
use Symfony\Component\HttpFoundation\RedirectResponse
class DefaultController extends Controller{
/** * @Route(“/”, name=”homepage”)
*/public function homepageAction(){
$respose = new RedirectResponse($this->generateUrl('homepage_natale'));
[..]
return $response;}
}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
use Symfony\Component\HttpFoundation\RedirectResponse
class DefaultController extends Controller{
/** * @Route(“/”, name=”homepage”)
*/public function homepageAction(){
$respose = new RedirectResponse($this->generateUrl('homepage_natale'));
[..]
return $response;}
}
http://traintosymfony.com66 Emanuele Gaspari
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
class DefaultController extends Controller{
/** * @Route("/chisiamo", name=”chisiamo”)
*/public function chisiamoAction(){
return $this->redirect($this->generateUrl('homepage_contatti'), 301);}
}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
class DefaultController extends Controller{
/** * @Route("/chisiamo", name=”chisiamo”)
*/public function chisiamoAction(){
return $this->redirect($this->generateUrl('homepage_contatti'), 301);}
}
redirect permanente
redirect permanente con codice di stato HTTP 301
http://traintosymfony.com67 Emanuele Gaspari
Routes
Controller e Action
specificare una Route
Routes parametriche
annotation @Route
collisione di urls
Controller Naming Pattern
Request
oggetto Request
i parametri
Response
oggetto Response
redirect
parametri per il template
ROUTING
http://traintosymfony.com68 Emanuele Gaspari
l'azione può passare delle variabili al template restituendo un array
public function showAction($codice){
[...]return array(
'entity' => $entity,'show_extended_version' => true
);}
public function showAction($codice){
[...]return array(
'entity' => $entity,'show_extended_version' => true
);}
utilizzabili nel template twig
{% if show_extended_version %}[...]
{% else %}<a href=”...”>
{{ entity.codice }}</a>
{% endif %}
{% if show_extended_version %}[...]
{% else %}<a href=”...”>
{{ entity.codice }}</a>
{% endif %}
TRAINTO SYMFONY
Verona, 13•14 Aprile 2013
the frameworkshop
http://traintosymfony.com@TrainToSymfony
Media partner:©Copyright Emanuele Gaspari Castelletti