SlideShare ist ein Scribd-Unternehmen logo
1 von 69
Downloaden Sie, um offline zu lesen
http://traintosymfony.com1
Emanuele Gaspari
TRAIN
TO SYMFONY
Verona, 13•14 Aprile 2013
the frameworkshop
http://traintosymfony.com
@TrainToSymfony
Media partner:
Routing (2/3)
http://traintosymfony.com2
Emanuele Gaspari
about me
creatore di SymfonyBricks
Emanuele Gaspari
ultimo sito pubblicato (copiaincolla): www.ilovesanmartino.it
4 bundles
21 controllers
6 services
9 entities
5 repositories custom
4 estensioni twig
14 macros
10 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 seconda parte:
il sistema di Routing in Symfony
http://traintosymfony.com4
Emanuele Gaspari
Routing
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 Gaspari
Controller
SymfonyBundleFrameworkBundleControllerController
●
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 Gaspari
actions: esempi
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
class DefaultController extends Controller
{
public function homepageAction()
{
[...]
}
public function contattiAction()
{
[...]
}
public function chiSiamoAction()
{
[...]
}
}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
class DefaultController extends Controller
{
public function homepageAction()
{
[...]
}
public function contattiAction()
{
[...]
}
public function chiSiamoAction()
{
[...]
}
}
http://traintosymfony.com9
Emanuele Gaspari
scopo di un'azione
lo scopo di un'azione è di preparare i dati
che verranno mostrati nel template
le azioni non dovrebbero essere molto estese
se un'azione lo è, chiediti se la logica debba essere
ridistribuita 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
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
class DefaultController extends Controller
{
public function homepageAction()
{
return $this->render(
'TtsDemoBundle:Default:homepage.html.twig'
);
}
}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
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
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
class CatalogoController extends Controller
{
public function indexAction()
{
[...]
}
}
# src/Tts/DemoBundle/Controller/CatalogoController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
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 passate
all'azione come argomenti
http://traintosymfony.com16
Emanuele Gaspari
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
namespace TtsDemoBundleController;
use SmfonyBundleFrameworkBundleControllerController;
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
<?php
namespace TtsDemoBundleController;
use SmfonyBundleFrameworkBundleControllerController;
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
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
class DefaultController extends Controller
{
/**
* @Route("/", name=”homepage”)
*/
public function homepageAction() {
[...]
}
}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
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
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
class CatalogoController extends Controller
{
/**
* @Route("/catalogo", name=”index_catalogo”)
*/
public function indexAction() {
[...]
}
}
# src/Tts/DemoBundle/Controller/CatalogoController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
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
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
class ProdottoController extends Controller
{
/**
* @Route("/prodotto/{codice}", name=”prodotto_show”)
*/
public function showAction($codice) {
[...]
}
}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
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
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
class ProdottoController extends Controller
{
/**
* @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”)
*/
public function showAction($categoria, $codice, $slug) {
[...]
}
}
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
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 Gaspari
type: annotation
# app/config/config.yml
# TtsDemoBundle Default controller
default:
resource: “@TtsDemoBundle/Controller/DefaultController.php”
type: annotation
# TtsDemoBundle Catalogo controller
catalogo:
resource: “@TtsDemoBundle/Controller/CatalogoController.php”
type: annotation
# TtsDemoBundle Prodotto controller
prodotto:
resource: “@TtsDemoBundle/Controller/ProdottoController.php”
type: annotation
# app/config/config.yml
# TtsDemoBundle Default controller
default:
resource: “@TtsDemoBundle/Controller/DefaultController.php”
type: annotation
# TtsDemoBundle Catalogo controller
catalogo:
resource: “@TtsDemoBundle/Controller/CatalogoController.php”
type: annotation
# TtsDemoBundle Prodotto controller
prodotto:
resource: “@TtsDemoBundle/Controller/ProdottoController.php”
type: annotation
http://traintosymfony.com27
Emanuele Gaspari
type: annotation (2)
# app/config/config.yml
# TtsDemoBundle
tts_demo:
resource: “@TtsDemoBundle/Controller/”
type: annotation
# app/config/config.yml
# TtsDemoBundle
tts_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_show
GET /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/index
GET /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 che
all'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/index
GET /prodotto/EG-124
non c'è più collisione tra Routes
non 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 una
specifica classe e metodo (Controller e Action)
bundle:controller:action
nome logico di un Controller
sintassi per riferirsi ad un'azione da qualunque punto dell'applicazione
Controller Naming Pattern
http://traintosymfony.com36
Emanuele Gaspari
TtsDemoBundle:Default:homepage
Bundle Controller Metodo
TtsDemoBundleTtsDemoBundle DefaultControllerDefaultController homepageAction()homepageAction()
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
class DefaultController extends Controller
{
public function homepageAction()
{
[…]
}
}
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
namespace TtsDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
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 Gaspari
oggetto Request
SymfonyComponentHttpFoundationRequest
oggetto che ho a disposizione all'interno di ogni azione
per gestire tutti i parametri della richiesta
Symfony utilizza un oggetto Request per modellare una richiesta HTTP
http://traintosymfony.com41
Emanuele Gaspari
accedere ad un oggetto Request
<?php
public function homepageAction()
{
$request = $this->getRequest();
}
<?php
public function homepageAction()
{
$request = $this->getRequest();
}
use SymfonyComponentHttpFoundationRequest;
$request = Request::createFromGlobals();
use SymfonyComponentHttpFoundationRequest;
$request = Request::createFromGlobals();
accedere a Request in una Action:
accedere a Request da qualunque punto dell'applicazione (in PHP):
$this->getRequest() => 0.04 Kb
Request::createFromGlobals() => 7.07 Kb
{{ app.request }}{{ app.request }}
accedere a Request da twig:
http://traintosymfony.com42
Emanuele Gaspari
panoramica
$_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'ordine
possono non essere specificati tutti
l'ordine è importante, per associare i parametri dell'url
404 GET /prodotto/nuovi/EG-124
404 GET /prodotto/nuovi/EG-124/
http://traintosymfony.com45
Emanuele Gaspari
defaults (1)
200 GET /prodotto/nuovi/EG-124/eg-124-new-hammer
200 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 Gaspari
accesso ai parametri
200 GET /prodotto/nuovi/EG-124/eg-124-new-hammer?color=red
200 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 Gaspari
Response
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 Gaspari
return array
la situazione più semplice è quella in cui utilizzo
l'annotation @Template e la mia Action restituisce
semplicemente un array
http://traintosymfony.com51
Emanuele Gaspari
return array
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationTemplate;
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 SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationTemplate;
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 Gaspari
render()
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 Gaspari
costruire una Response
è possibile anche costruire un oggetto Response
utile nel caso in cui abbia necessità di costruire la risposta
in più passaggi a seconda di variabili
o di effettuare delle operazioni successivamente
http://traintosymfony.com55
Emanuele Gaspari
costruire una Response
utilizzo la funzione $this->renderView() per memorizzare
un 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 SymfonyComponentHttpFoundationResponse;
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 SymfonyComponentHttpFoundationResponse;
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 SymfonyComponentHttpFoundationResponse;
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 SymfonyComponentHttpFoundationResponse;
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 Gaspari
json
anche restituire una risposta in formato json è semplice
http://traintosymfony.com59
Emanuele Gaspari
json Response
# src/Tts/DemoBundle/Controller/ProdottoController.php
<?php
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationJsonResponse;
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 SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationJsonResponse;
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 Gaspari
riassunto
●
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 Gaspari
redirect
il redirect è un messaggio al browser
cambia 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 Gaspari
redirect 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 Gaspari
RedirectResponse
c'è un oggetto dedicato (che sorpresa!) che la Action può
restituire in caso di redirect: RedirectResponse
http://traintosymfony.com65
Emanuele Gaspari
RedirectResponse
# src/Tts/DemoBundle/Controller/DefaultController.php
<?php
use SymfonyComponentHttpFoundationRedirectResponse
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 SymfonyComponentHttpFoundationRedirectResponse
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 %}
TRAIN
TO SYMFONY
Verona, 13•14 Aprile 2013
the frameworkshop
http://traintosymfony.com
@TrainToSymfony
Media partner:©Copyright Emanuele Gaspari Castelletti

Weitere ähnliche Inhalte

Ähnlich wie Routing (2/3) | Train to Symfony

Ähnlich wie Routing (2/3) | Train to Symfony (20)

TYPO3 Versione 10.2 - Le novita
TYPO3 Versione 10.2 - Le novitaTYPO3 Versione 10.2 - Le novita
TYPO3 Versione 10.2 - Le novita
 
eZ publish - Extension
eZ publish - ExtensioneZ publish - Extension
eZ publish - Extension
 
TYPO3 CMS 8.2 e TYPO3 CMS 8.3 - Le novità
TYPO3 CMS 8.2 e TYPO3 CMS 8.3 - Le novitàTYPO3 CMS 8.2 e TYPO3 CMS 8.3 - Le novità
TYPO3 CMS 8.2 e TYPO3 CMS 8.3 - Le novità
 
Mageploy presentato al Mage::day() 2013
Mageploy presentato al Mage::day() 2013Mageploy presentato al Mage::day() 2013
Mageploy presentato al Mage::day() 2013
 
Gae python gdg milano L03
Gae python gdg milano L03Gae python gdg milano L03
Gae python gdg milano L03
 
introduzione a symfony 2
introduzione a symfony 2 introduzione a symfony 2
introduzione a symfony 2
 
Enterprise Applications - Angular Day 2018
Enterprise Applications - Angular Day 2018Enterprise Applications - Angular Day 2018
Enterprise Applications - Angular Day 2018
 
Primo Incontro Con Scala
Primo Incontro Con ScalaPrimo Incontro Con Scala
Primo Incontro Con Scala
 
Django: utilizzo avanzato e nuove funzionalità
Django: utilizzo avanzato e nuove funzionalitàDjango: utilizzo avanzato e nuove funzionalità
Django: utilizzo avanzato e nuove funzionalità
 
Qt Lezione3: un visualizzatore di immagini
Qt Lezione3: un visualizzatore di immaginiQt Lezione3: un visualizzatore di immagini
Qt Lezione3: un visualizzatore di immagini
 
A static Analyzer for Finding Dynamic Programming Errors
A static Analyzer for Finding Dynamic Programming ErrorsA static Analyzer for Finding Dynamic Programming Errors
A static Analyzer for Finding Dynamic Programming Errors
 
Sviluppare un plugin WordPress da zero - WordCamp Bologna 2018
Sviluppare un plugin WordPress da zero - WordCamp Bologna 2018Sviluppare un plugin WordPress da zero - WordCamp Bologna 2018
Sviluppare un plugin WordPress da zero - WordCamp Bologna 2018
 
PHP Template Engine (introduzione)
PHP Template Engine (introduzione)PHP Template Engine (introduzione)
PHP Template Engine (introduzione)
 
Sviluppare estensioni per google chrome
Sviluppare estensioni per google chromeSviluppare estensioni per google chrome
Sviluppare estensioni per google chrome
 
Aumentiamo la sicurezza in TYPO3
Aumentiamo la sicurezza in TYPO3Aumentiamo la sicurezza in TYPO3
Aumentiamo la sicurezza in TYPO3
 
Topog presentation
Topog presentationTopog presentation
Topog presentation
 
TYPO3 CMS 9.1 - Le novità
TYPO3 CMS 9.1 - Le novitàTYPO3 CMS 9.1 - Le novità
TYPO3 CMS 9.1 - Le novità
 
Matteo baccan raspberry pi - linox 2015 - corso parte 2
Matteo baccan   raspberry pi - linox 2015 - corso parte 2Matteo baccan   raspberry pi - linox 2015 - corso parte 2
Matteo baccan raspberry pi - linox 2015 - corso parte 2
 
Web Performance Optimization
Web Performance OptimizationWeb Performance Optimization
Web Performance Optimization
 
Openmoko
OpenmokoOpenmoko
Openmoko
 

Routing (2/3) | Train to Symfony

  • 1. http://traintosymfony.com1 Emanuele Gaspari TRAIN TO SYMFONY Verona, 13•14 Aprile 2013 the frameworkshop http://traintosymfony.com @TrainToSymfony Media partner: Routing (2/3)
  • 2. http://traintosymfony.com2 Emanuele Gaspari about me creatore di SymfonyBricks Emanuele Gaspari ultimo sito pubblicato (copiaincolla): www.ilovesanmartino.it 4 bundles 21 controllers 6 services 9 entities 5 repositories custom 4 estensioni twig 14 macros 10 bundles aggiuntivi (FOSUserBundle, FOSJsRoutingBundle, KnpPaginatorBundle, CopiaincollaMetaTagsBundle, etc..) co-sviluppatore di CopiaincollaMetaTagsBundle https://github.com/copiaincolla/MetaTagsBundle https://symfonybricks.com inmarelibero@gmail.com @inmarelibero
  • 3. 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
  • 4. http://traintosymfony.com4 Emanuele Gaspari Routing il Routing è il meccanismo di associazione tra url e controllers
  • 5. 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
  • 6. http://traintosymfony.com6 Emanuele Gaspari Controller SymfonyBundleFrameworkBundleControllerController ● 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
  • 7. 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
  • 8. http://traintosymfony.com8 Emanuele Gaspari actions: esempi # src/Tts/DemoBundle/Controller/DefaultController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; class DefaultController extends Controller { public function homepageAction() { [...] } public function contattiAction() { [...] } public function chiSiamoAction() { [...] } } # src/Tts/DemoBundle/Controller/DefaultController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; class DefaultController extends Controller { public function homepageAction() { [...] } public function contattiAction() { [...] } public function chiSiamoAction() { [...] } }
  • 9. http://traintosymfony.com9 Emanuele Gaspari scopo di un'azione lo scopo di un'azione è di preparare i dati che verranno mostrati nel template le azioni non dovrebbero essere molto estese se un'azione lo è, chiediti se la logica debba essere ridistribuita in altri servizi, repository, entities
  • 10. 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
  • 11. 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
  • 12. 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 <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; class DefaultController extends Controller { public function homepageAction() { return $this->render( 'TtsDemoBundle:Default:homepage.html.twig' ); } } # src/Tts/DemoBundle/Controller/DefaultController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; class DefaultController extends Controller { public function homepageAction() { return $this->render( 'TtsDemoBundle:Default:homepage.html.twig' ); } } /
  • 13. 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 <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; class CatalogoController extends Controller { public function indexAction() { [...] } } # src/Tts/DemoBundle/Controller/CatalogoController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; class CatalogoController extends Controller { public function indexAction() { [...] } } /catalogo
  • 14. 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
  • 15. http://traintosymfony.com15 Emanuele Gaspari stabilisco che una parte del path è variabile Routes {parametriche} le parti variabili sono comprese tra { } e vengono passate all'azione come argomenti
  • 16. http://traintosymfony.com16 Emanuele Gaspari # src/Tts/DemoBundle/Controller/ProdottoController.php <?php namespace TtsDemoBundleController; use SmfonyBundleFrameworkBundleControllerController; 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 <?php namespace TtsDemoBundleController; use SmfonyBundleFrameworkBundleControllerController; 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}
  • 17. 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}
  • 18. 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
  • 19. 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
  • 20. 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
  • 21. http://traintosymfony.com21 Emanuele Gaspari = # src/Tts/DemoBundle/Controller/DefaultController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; class DefaultController extends Controller { /** * @Route("/", name=”homepage”) */ public function homepageAction() { [...] } } # src/Tts/DemoBundle/Controller/DefaultController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; class DefaultController extends Controller { /** * @Route("/", name=”homepage”) */ public function homepageAction() { [...] } } # app/config/routing.yml homepage: path: / defaults: { _controller: TtsDemoBundle:Default:homepage }
  • 22. http://traintosymfony.com22 Emanuele Gaspari # app/config/routing.yml index_catalogo: path: /catalogo defaults: { _controller: TtsDemoBundle:Catalogo:index } # src/Tts/DemoBundle/Controller/CatalogoController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; class CatalogoController extends Controller { /** * @Route("/catalogo", name=”index_catalogo”) */ public function indexAction() { [...] } } # src/Tts/DemoBundle/Controller/CatalogoController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; class CatalogoController extends Controller { /** * @Route("/catalogo", name=”index_catalogo”) */ public function indexAction() { [...] } } =
  • 23. 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 <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; class ProdottoController extends Controller { /** * @Route("/prodotto/{codice}", name=”prodotto_show”) */ public function showAction($codice) { [...] } } # src/Tts/DemoBundle/Controller/ProdottoController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; class ProdottoController extends Controller { /** * @Route("/prodotto/{codice}", name=”prodotto_show”) */ public function showAction($codice) { [...] } } =
  • 24. 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 <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; class ProdottoController extends Controller { /** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */ public function showAction($categoria, $codice, $slug) { [...] } } # src/Tts/DemoBundle/Controller/ProdottoController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; class ProdottoController extends Controller { /** * @Route("/prodotto/{categoria}/{codice}/{slug}", name=”prodotto_show”) */ public function showAction($categoria, $codice, $slug) { [...] } } =
  • 25. http://traintosymfony.com25 Emanuele Gaspari definisco in app/config/routing.yml quali controller caricare
  • 26. http://traintosymfony.com26 Emanuele Gaspari type: annotation # app/config/config.yml # TtsDemoBundle Default controller default: resource: “@TtsDemoBundle/Controller/DefaultController.php” type: annotation # TtsDemoBundle Catalogo controller catalogo: resource: “@TtsDemoBundle/Controller/CatalogoController.php” type: annotation # TtsDemoBundle Prodotto controller prodotto: resource: “@TtsDemoBundle/Controller/ProdottoController.php” type: annotation # app/config/config.yml # TtsDemoBundle Default controller default: resource: “@TtsDemoBundle/Controller/DefaultController.php” type: annotation # TtsDemoBundle Catalogo controller catalogo: resource: “@TtsDemoBundle/Controller/CatalogoController.php” type: annotation # TtsDemoBundle Prodotto controller prodotto: resource: “@TtsDemoBundle/Controller/ProdottoController.php” type: annotation
  • 27. http://traintosymfony.com27 Emanuele Gaspari type: annotation (2) # app/config/config.yml # TtsDemoBundle tts_demo: resource: “@TtsDemoBundle/Controller/” type: annotation # app/config/config.yml # TtsDemoBundle tts_demo: resource: “@TtsDemoBundle/Controller/” type: annotation o, semplicemente, specifico la cartella che li contiene tutti
  • 28. 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
  • 29. http://traintosymfony.com29 Emanuele Gaspari best practice far corrispondere ad ogni url una sola route
  • 30. http://traintosymfony.com30 Emanuele Gaspari GET /prodotto/EG-124 => prodotto_show GET /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
  • 31. 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/index GET /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
  • 32. 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 che all'interno di un Controller una funzione venga spostata in alto solo perché la Route venga esaminata prima l'ordine non basta
  • 33. 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/index GET /prodotto/EG-124 non c'è più collisione tra Routes non mi affido più all'ordine di caricamento soluzione 2, parametro requirements pongo dei vincoli sul formato di un parametro di una Route
  • 34. 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
  • 35. http://traintosymfony.com35 Emanuele Gaspari Symfony associa il nome logico ad una specifica classe e metodo (Controller e Action) bundle:controller:action nome logico di un Controller sintassi per riferirsi ad un'azione da qualunque punto dell'applicazione Controller Naming Pattern
  • 36. http://traintosymfony.com36 Emanuele Gaspari TtsDemoBundle:Default:homepage Bundle Controller Metodo TtsDemoBundleTtsDemoBundle DefaultControllerDefaultController homepageAction()homepageAction() # src/Tts/DemoBundle/Controller/DefaultController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; class DefaultController extends Controller { public function homepageAction() { […] } } # src/Tts/DemoBundle/Controller/DefaultController.php <?php namespace TtsDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; class DefaultController extends Controller { public function homepageAction() { […] } } Controller Naming Pattern
  • 37. http://traintosymfony.com37 Emanuele Gaspari # template twig {{ render(controller(“TtsDemoBundle:Blog:latestPosts”, {“max”: 5})) }} # template twig {{ render(controller(“TtsDemoBundle:Blog:latestPosts”, {“max”: 5})) }} esempio
  • 38. 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
  • 39. 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
  • 40. http://traintosymfony.com40 Emanuele Gaspari oggetto Request SymfonyComponentHttpFoundationRequest oggetto che ho a disposizione all'interno di ogni azione per gestire tutti i parametri della richiesta Symfony utilizza un oggetto Request per modellare una richiesta HTTP
  • 41. http://traintosymfony.com41 Emanuele Gaspari accedere ad un oggetto Request <?php public function homepageAction() { $request = $this->getRequest(); } <?php public function homepageAction() { $request = $this->getRequest(); } use SymfonyComponentHttpFoundationRequest; $request = Request::createFromGlobals(); use SymfonyComponentHttpFoundationRequest; $request = Request::createFromGlobals(); accedere a Request in una Action: accedere a Request da qualunque punto dell'applicazione (in PHP): $this->getRequest() => 0.04 Kb Request::createFromGlobals() => 7.07 Kb {{ app.request }}{{ app.request }} accedere a Request da twig:
  • 43. 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
  • 44. 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'ordine possono non essere specificati tutti l'ordine è importante, per associare i parametri dell'url 404 GET /prodotto/nuovi/EG-124 404 GET /prodotto/nuovi/EG-124/
  • 45. http://traintosymfony.com45 Emanuele Gaspari defaults (1) 200 GET /prodotto/nuovi/EG-124/eg-124-new-hammer 200 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 = “-”) { [...] }
  • 46. http://traintosymfony.com46 Emanuele Gaspari accesso ai parametri 200 GET /prodotto/nuovi/EG-124/eg-124-new-hammer?color=red 200 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”); [...] }
  • 47. 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}
  • 48. 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
  • 49. http://traintosymfony.com49 Emanuele Gaspari Response 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”
  • 50. http://traintosymfony.com50 Emanuele Gaspari return array la situazione più semplice è quella in cui utilizzo l'annotation @Template e la mia Action restituisce semplicemente un array
  • 51. http://traintosymfony.com51 Emanuele Gaspari return array # src/Tts/DemoBundle/Controller/ProdottoController.php <?php use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; use SensioBundleFrameworkExtraBundleConfigurationTemplate; 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 SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; use SensioBundleFrameworkExtraBundleConfigurationTemplate; 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); }
  • 52. http://traintosymfony.com52 Emanuele Gaspari render() 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
  • 53. 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()
  • 54. http://traintosymfony.com54 Emanuele Gaspari costruire una Response è possibile anche costruire un oggetto Response utile nel caso in cui abbia necessità di costruire la risposta in più passaggi a seconda di variabili o di effettuare delle operazioni successivamente
  • 55. http://traintosymfony.com55 Emanuele Gaspari costruire una Response utilizzo la funzione $this->renderView() per memorizzare un contenuto HTML in una variabile creo un oggetto Response con quella variabile come primo argomentoimpostando
  • 56. http://traintosymfony.com56 Emanuele Gaspari # src/Tts/DemoBundle/Controller/ProdottoController.php <?php use SymfonyComponentHttpFoundationResponse; 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 SymfonyComponentHttpFoundationResponse; 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); }
  • 57. http://traintosymfony.com57 Emanuele Gaspari # src/Tts/DemoBundle/Controller/ProdottoController.php <?php use SymfonyComponentHttpFoundationResponse; 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 SymfonyComponentHttpFoundationResponse; 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(); }
  • 58. http://traintosymfony.com58 Emanuele Gaspari json anche restituire una risposta in formato json è semplice
  • 59. http://traintosymfony.com59 Emanuele Gaspari json Response # src/Tts/DemoBundle/Controller/ProdottoController.php <?php use SymfonyComponentHttpFoundationResponse; use SymfonyComponentHttpFoundationJsonResponse; 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 SymfonyComponentHttpFoundationResponse; use SymfonyComponentHttpFoundationJsonResponse; 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; }
  • 60. http://traintosymfony.com60 Emanuele Gaspari riassunto ● un array ● $this->render() ● $this->renderView() ● un oggetto Response ● un oggetto JsonResponse abbiamo visto che un'azione può utilizzare: ...e può fare molto altro!
  • 61. 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
  • 62. http://traintosymfony.com62 Emanuele Gaspari redirect il redirect è un messaggio al browser cambia 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
  • 63. http://traintosymfony.com63 Emanuele Gaspari redirect 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
  • 64. http://traintosymfony.com64 Emanuele Gaspari RedirectResponse c'è un oggetto dedicato (che sorpresa!) che la Action può restituire in caso di redirect: RedirectResponse
  • 65. http://traintosymfony.com65 Emanuele Gaspari RedirectResponse # src/Tts/DemoBundle/Controller/DefaultController.php <?php use SymfonyComponentHttpFoundationRedirectResponse 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 SymfonyComponentHttpFoundationRedirectResponse class DefaultController extends Controller { /** * @Route(“/”, name=”homepage”) */ public function homepageAction() { $respose = new RedirectResponse($this->generateUrl('homepage_natale')); [..] return $response; } }
  • 66. 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
  • 67. 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
  • 68. 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 %}
  • 69. TRAIN TO SYMFONY Verona, 13•14 Aprile 2013 the frameworkshop http://traintosymfony.com @TrainToSymfony Media partner:©Copyright Emanuele Gaspari Castelletti