Un controller (o controllore) in Symfony2 è un metodo PHP contenuto all'interno di una classe che riceve informazioni da una richiesta HTTP e restituisce una risposta HTTP.
Definire un controller
Come già anticipato, per creare un nostro controller dobbiamo creare una classe all'interno della cartella Controller
del nostro bundle ed il nome del file deve avere il suffisso Controller
.
Iniziamo, quindi, a creare il nostro primo controllore. Apriamo il DemoBundle
e creiamo il file TestController.php
dentro la cartella Controller
. A questo punto inseriamo il seguente codice:
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class TestController extends Controller
{
public function indexAction()
{
//...
}
}
Ogni metodo deve restituire un oggetto Response (abbiamo infatti richiamato la classe Response) e deve terminare con il suffisso Action
. La classe del nostro controllore, per comodità, estende la classe Controller
contenuto all'interno del FrameworkBundle
.
Prima di procedere oltre apportiamo una piccola modifica alle rotte che abbiamo creato nell'articolo precedente; facciamo in modo che la rotta _test
punti alla nostra nuova classe anziché alla classe WelcomeController
. Per fare ciò modifichiamo l'array defaults in questa maniera:
defaults: { _controller: AcmeDemoBundle:Test:index, page: 1 }
A questo punto, se proviamo ad aprire il browser all'indirizzo /app_dev.php/test
si solleverà un'eccezione con il seguente messaggio:
The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller?
Questo perché, come già detto, il nostro controller deve per forza restituire un oggetto Response
. Creiamo quindi una semplice risposta e all'interno del metodo indexAction
inseriamo:
$response = new Response();
return $response->setContent('test');
Ora, se ricarichiamo la pagina del browser, noteremo che verrà stampata a schermo la stringa test.
Se ricontrolliamo con attenzione la nostra rotta, vediamo che utilizza un parametro page
che però non abbiamo definito da nessuna parte nel controller. In Symfony, gli argomenti passati alle rotte, vengono definiti come parametri dell'azione, cioè del metodo. In questo caso, quindi, modifichiamo la firma del metodo indexAction
in maniera da accettare un parametro ed utilizziamolo all'interno del metodo:
public function indexAction( $page )
{
$response = new Response();
return $response->setContent('Questa è la pagina ' . $page);
}
Ricaricando il browser visualizzeremo il numero di pagina attuale. Possiamo anche utilizzare del codice HTML come risposta:
return $response->setContent('<html><head></head><body>Questa è la pagina ' . $page . '</body></html>');
Notiamo che, dato che stiamo lavorando sull'ambiente dev, ora che abbiamo stampato del codice HTML viene anche aggiunta la toolbar di Symfony che può darci molte informazioni utili in fase di debug.
Ovviamente non avremo bisogno di scrivere a mano tutto il codice HTML all'interno del controller, si perderebbe l'utilità di adottare un pattern MVC. Vedremo nella prossima lezione come utilizzare le viste e, in particolare Twig, per reindirizzare la pagina. Per ora possiamo vedere un esempio sostituendo il valore di ritorno del metodo con il codice:
return $this->render('AcmeDemoBundle:Welcome:index.html.twig');
Di default il content-type restituito è text/html; charset=UTF-8
ma, in caso di esigenze differenti possiamo modificarlo e restituirne uno customizzato. Utile, ad esempio, se dobbiamo restituire un valore in JSON, in XML, ecc.
Per una pagina in formato JSON, ad esempio, possiamo modificare il metodo in questa maniera:
public function indexAction( $page )
{
$names = json_encode( array(
'simone',
'josephine',
'giuseppe',
'gabriele',
'renato'
) );
$response = new Response();
$response->headers->set('Content-Type', 'application/json');
return $response->setContent( $names );
}
Come abbiamo anticipato all'inizio della lezione, un controllore restituisce una risposta HTTP, quindi quello che abbiamo fatto è stato modificare uno degli argomenti dell'header della risposta impostandolo su application/json
.
Generazione degli URL
Spesso si ha la necessità di generare l'URL di una determinata rotta. Per fare ciò, Symfony ci mette a disposizione un metodo molto utile generateUrl
$this->generateUrl('rotta');
$this->generateUrl('rotta', array('parametro' => 'valore'));
Dal codice proposto possiamo notare che vengono presi due parametri in ingresso:
- la rotta;
- un array di coppie parametro, valore per eventuali parametri della rotta
Redirect ed inoltro
Se si ha la necessità di effettuare un redirect verso una rotta, possiamo utilizzare il metodo redirect
:
return $this->redirect($this->generateUrl('rotta'));
Se invece vogliamo richiamare un controllore senza eseguire un redirect, possiamo effettuare una chiamata interna verso il controllore attraverso il metodo forward
:
return $this->forward('AcmeDemoBundle:Welcome:index');
Nell'esempio appena visto richiamiamo l'azione indexAction
contenuta nella classe WelcomeController
senza che si modifichi l'URL e venga effettuato un redirect.
Una volta analizzati nel dettaglio anche i controller, potremo passare all'analisi delle viste, argomento al quale verrà dedicato il prossimo capitolo.