Il routing è uno degli aspetti fondamentali di qualsiasi web framework moderno in quanto permette di mappare URI specifici a determinate azioni all’interno dell’applicazione. In sostanza, il routing determina come l’applicazione risponde ad ogni singola richiesta HTTP.
Grazie alla configurazione del routing in Symfony, quando l’applicazione riceve una richiesta è in grado di invocare il metodo corretto di una determinata classe controller per generare una risposta.
Come configurare il routing in Simfony
Le rotte possono essere configurate in vari formati, ovvero YAML, XML, PHP o tramite PHP Attributes. Tutti questi formati sono intercambiabili tra di loro in quanto offrono le stesse funzionalità e le stesse performance. Le best practices di Symfony consigliano di utilizzare gli attributes in quanto, come già visto nel controller HelloController, sono definite assieme alla funzione controller, nello stesso file, evitando così di dover gestire più file in formati e cartelle differenti.
Di seguito, una overview sulla configurazione delle route nei vari formati possibili. Successivamente, ci concentreremo solo sull’utilizzo dei PHP Attributes.
Configurare una route con PHP Attributes
Gli attributes in PHP sono una caratteristica introdotta con PHP 8.0. Essi forniscono un modo per aggiungere meta-dati a classi, metodi, proprietà e parametri, simili a quelle che vengono chiamate annotations in altri linguaggi di programmazione. Nel caso delle route, prendiamo l’esempio del nostro HelloController in cui abbiamo definito il path /hello
class HelloController extends AbstractController { #[Route('/hello', name: 'app_hello')] public function index(): Response { return $this->render('hello/index.html.twig', [ 'controller_name' => 'HelloController', ]); }
Questa configurazione definisce una route chiamata app_hello che mappa l’URI /hello al metodo index() della classe HelloController.
Configurare una route con YAML
La stessa route può essere configurata tramite YAML. Per farlo, è necessario creare un file nella cartella config chiamato routes.yaml.
# config/routes.yaml app_hello: path: /hello controller: App\Controller\HelloController::index
Configurare una route con XML
Utilizzando il formato XML, la route può essere configurata nel seguente modo:
<!-- config/routes.xml --> <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="app_hello" path="/hello" controller="App\Controller\HelloController::index"/> </routes>
Nb. Il file routes.xml deve essere creato in config.
Configurare una route con PHP
Per configurare le route tramite PHP è necessario creare il file routes.php nella directory config:
// config/routes.php use App\Controller\HelloController; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; return function (RoutingConfigurator $routes): void { $routes->add('app_hello', '/hello) ->controller([HelloController::class, 'index']) ; };
Specializzare le route con le opzioni methods e condition
La route app_hello precedentemente definita non specifica alcun metodo HTTP. In questa casistica, Symfony permette di contattare tale route con qualsiasi metodo come GET e POST. Utilizzando l’opzione methods è possibile limitare l’accesso alla route ad uno o più metodi HTTP.
Supponiamo di voler abilitare la route /hello solo per le chiamate GET e HEAD. Il codice verrà modificato nel seguento modo:
#[Route('/hello', name: 'app_hello', methods: ['GET', 'HEAD'])]
Un’altra opzione che è possibile utilizzare nella configurazione delle route è condition. Essa permette di abilitare la route solo quando si verificano determinate condizioni logiche. La sintassi delle espressioni deve seguire quella del componente ExpressionLanguage di Symfony.
Supponiamo, ad esempio, di voler attivare il path /hello solo per le chiamate GET e che contengono nell’header della richiesta un attributo chiamato “APPLICATION-KEY”:
#[Route( '/hello, name: 'app_hello', condition: "context.getMethod() == 'GET' and request.headers.has('APPLICATION-KEY')" )]
Parametri delle route in Symfony
Fino a questo momento, abbiamo visto come associare un path statico ad una route. Spesso, però, si ha la necessità di ricevere in input dei valori da parte del client per poter eseguire delle elaborazioni specifiche. Ad esempio, in un blog, per accedere al contenuto di articolo potremmo pensare di creare una route /articolo. Tale route è uguale per ogni articolo. Per specificare a quale articolo si è interessati, è necessario introdurre il concetto di parametri dinamici delle route.
Infatti, un parametro dinamico è un valore variabile che può essere fornito ad una route.
In Symfony, ad una route possono essere associati uno o più parametri. Per farlo, è sufficiente usare la seguente sintassi:
/path/{nome del parametro}
Nel caso dell’articolo di un blog, la definizione della route potrebbe essere la seguente:
/articolo/{id}
{id} è il parametro dinamico che rappresenta l’id di un articolo. Quando un utente visita, ad esempio, l’URL /articolo/43, il valore 43 viene fornito al controller all’interno della variabile id. In questo modo, il controller può richiedere al database l’articolo tramite il suo identificativo univoco.
Esempio di una route con parametro
A scopo dimostrativo, creiamo un nuovo metodo all’interno della solita classe HelloController:
#[Route('/hello/random/{max}', name: 'app_hello_random')] public function randomNumber(int $max): Response { $number = random_int(0, $max); return new Response("Numero casuale: $number"); }
La route sopra definita /hello/random/{max} prevede un parametro dinamico chiamato max. Il metodo controller randomNumber associato alla route genera e fornisce in output un numero casuale che va da 0 fino al valore del parametro ricevuto in input. Accedendo alla URL symfony-test.local/hello/random/100 otterremo un numero casuale tra 0 e 100:
La funzione randomNumber ha utilizzato correttamente il parametro ricevuto. Se, però, al posto di un parametro numerico, inseriamo un valore di tipo stringa, otteniamo la seguente schermata:
Symfony ha risposto con un errore del server (500 Internal Server Error) perchè randomNumber ha specificato nella firma del metodo un parametro id di tipo int, mentre noi abbiamo fornito un valore testuale.