🎃 Grandes descuentos en libros en línea, eformaciones y vídeos*. Código CALABAZA30. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí

El enrutado

Organización de la aplicación

En nuestra aplicación, por ahora, solo tenemos un controlador, TestController, y dentro de él, dos acciones: index() y redirection(). Es fácil imaginar que, en la práctica, tendrá varios controladores y acciones disponibles. Cada acción corresponderá a una solicitud del usuario.

Es importante plantearse la pregunta sobre cómo organizar la aplicación.

¿Cuántos controladores voy a tener?

¿Cuántas acciones tendré para cada controlador?

No hay reglas estrictas, pero no pierda de vista que, cuanto más «dividida» esté su aplicación, tanto mejor.

Para ayudarlo en su organización, recuerde que una acción permite mostrar una vista. En otras palabras, una acción puede definirse para la visualización de cada una de sus páginas.

Un controlador agrupará varias acciones. Se puede definir un controlador para cada tipo de página, por ejemplo. Una práctica común (aunque no la única) es tener un controlador para la parte del Front y un controlador que gestiona el Back, es decir, la administración de su sitio. Otro criterio para su organización es que sus acciones no deben ser demasiado extensas (un máximo de unas veinte o treinta líneas). Será más fácil probar y depurar (test & debug) una acción si...

La importancia de las rutas

Las rutas permiten, según una solicitud del usuario (una URL), encontrar el controlador y la acción que se ha de ejecutar.

Las rutas que permitirán ejecutar las acciones están definidas por defecto gracias a las anotaciones.

Retomemos nuestro TestController:

class TestController extends AbstractController  
{  
  
#[Route('/test', name: 'app_test',methods: ['GET', 'HEAD'] )]  
    public function index(Request $request): Response  
    {  
  
        $response=new Response();  
  
        $response->setContent('Hello World');  
        $response->headers->setCookie(Cookie::create('nombre', 'Yves')); 
        return $response;  
    }  
} 

La anotación #Route indica que la solicitud /test (localhost:8000/test en el navegador) ejecutará la acción que sigue, es decir, index(Request $request)

Pero ¿cómo sabe Symfony dónde está el controlador que se debe instanciar?

Todo esto está definido en el archivo de configuración....

Rutas sin anotaciones

Es posible no usar los attributes para las rutas. Podemos definir las rutas en un archivo YAML externo a la raíz de /config.

Este archivo ya está creado para este propósito: config/routes.yaml.

Vamos a indicar, por ejemplo, una nueva ruta (la llamaremos /testroute) para la acción index() del controlador TestController.

Añada al final del archivo config/routes.yaml, a la misma altura que controllers, las siguientes instrucciones (sin borrar las líneas ya contenidas en este archivo):

index:  
   path: /testroute  
   controller: App\Controller\TestController::index 

Pruebe esta nueva ruta con la URL: https://localhost:8000/testroute

Debería ver la página de prueba (con Hello World) o, en su defecto, la última redirección.

Por lo tanto, podemos definir una serie de rutas independientes en el archivo config/routes.yaml.

Sin embargo, los attributes son más prácticos, ya que se encuentran antes de cada acción y son más fáciles de manipular. En el resto de este libro, continuaremos utilizando las anotaciones para las rutas.

Los verbos de las rutas

Como sabe, una solicitud HTTP tiene un método de transmisión de parámetros llamado verbo.

Por ejemplo, una solicitud ejecutada directamente en un navegador tiene el verbo GET.

Una solicitud llamada mediante el envío de un formulario generalmente tiene el verbo POST.

Es posible especificar este método en la anotación de la ruta (por defecto, se elige el método GET):

#[Route('/test', name: 'app_test',methods: ['GET', 'POST'] )] 

Aquí, por ejemplo, autorizamos que la ruta /test se ejecute, ya sea con el método GET o con el método POST.

Especificar el verbo de la ruta permite un mejor control de la solicitud utilizada y puede evitar algunas vulnerabilidades de seguridad.

Por ejemplo, una acción que recupera datos a través del objeto $request con el método query (ejemplo: $request->query->get(’info’)) debe tener una ruta definida con el método GET obligatoriamente.

Los parámetros de las rutas

Es posible definir parámetros en una ruta (como en una función PHP). Estos parámetros se transmitirán automáticamente a la acción en el orden en que se indiquen.

Tomemos un ejemplo.

Creemos una tercera acción en TestController.

Llamémosla hello().

Apliquemos una ruta que se llamará /hello:

    #[Route('/hello', name: 'hello')]  
    public function hello()  
    {  
        $response=new Response("Hello!");   
    } 

Si deseamos transmitir el nombre y el apellido como parámetros de la ruta, debemos indicarlos entre {}, como se muestra a continuación:

    #[Route('/hello/{nombre}/{apellido}', name: 'hello')]  
    public function hello(Request $request,$nombre,$apellido)  
    {  
        return new Response("Hello $nombre $apellido!");   
  
    }   

Los parámetros se transmiten en el orden dado en la ruta y se recuperan en el método hello ($nombre y $apellido), prescindiendo también del objeto Request...

Parámetros condicionales

Es posible definir valores predeterminados para los parámetros de la acción.

Ejemplo

    #[Route('/hello/{nombre}/{apellido}', name: 'hello')] 
    public function hello(Request $request, $nombre,$apellido='') 
    {   
  
        return new Response("Hello $nombre $apellido!"); 
    } 

Aquí, $apellido=’’ significa que, si no especificamos el valor de este parámetro en la ruta, estará vacío por defecto.

Así, ya no es obligatorio especificar el parámetro del apellido en la solicitud (Guillen  se omite): https://localhost:8000/hello/David

Validación de parámetros

Siempre es prudente verificar los valores transmitidos por el cliente en la solicitud. De hecho, el cliente puede intentar enviar código en los parámetros (generalmente, en JavaScript) para ejecutar un proceso que pirateará sus datos. Este es el principio de una vulnerabilidad de seguridad llamada Cross-Site Scripting.

Para evitarlo, puede probar el tipo de los parámetros transmitidos (como en cualquier función PHP).

Tomemos un ejemplo.

Añadamos el parámetro edad en la ruta, pero especificando el tipo del parámetro en la acción hello():

    #[Route('/hello/{edad}/{nombre}/{apellido}', name: 'hello')]  
    public function hello(Request $request, int $adad, $nombre, $apellido='') 
    {  
  
        return new Response("Hello $nombre $apellido tiene $edad años!"); 
    } 

int $edad precisa que el parámetro $edad debe ser un entero.

Es posible profundizar más en las pruebas de los valores de los parámetros utilizando la opción requirements.

Esta opción permite definir para cada parámetro una expresión regular.

Una expresión regular es un patrón de datos al que debe ajustarse...

La lista de rutas

Es posible obtener la lista de las rutas presentes en toda la aplicación ejecutando en el terminal: php bin/console debug:router