Buy Access to Course
11.

MapQueryParameter y carga útil de la petición

|

Share this awesome video!

|

Keep on Learning!

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Las siguientes novedades de las que quiero hablar están relacionadas con la obtención de datos de la petición. Normalmente es un trabajo un poco aburrido. Pero las nuevas funciones son bastante chulas.

El atributo MapQueryParameter

Por ejemplo, añade un ?query=banana a la URL. Para obtenerlo en nuestro controlador, históricamente escribíamos un argumento con Request y lo cogíamos de ahí. Y aunque eso sigue funcionando, ahora podemos añadir un argumento ?string $query. Para decirle a Symfony que esto es algo que debe obtener de un parámetro de consulta, añade un atributo delante: #[MapQueryParameter].

Ya está Vuelca $query para probar que funciona.

64 lines | src/Controller/VinylController.php
// ... lines 1 - 11
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
// ... lines 13 - 15
class VinylController extends AbstractController
{
// ... lines 18 - 24
public function homepage(
#[MapQueryParameter] string $query = '',
): Response
{
dump($query);
// ... lines 30 - 42
}
// ... lines 44 - 62
}

De vuelta al mundo del navegador web, actualiza. En la barra de herramientas de depuración web... ¡ya está!

Validación a partir de la sugerencia de tipo

El atributo también tiene algunas opciones. Por ejemplo, si tu parámetro de consulta se llama de forma diferente a tu argumento, podrías ponerlo aquí.

Y más allá de coger el valor de la petición, este sistema también realiza la validación. Observa: duplica esto y añade un argumento int $page = 1. Ah, y quería que el argumento $query fuera opcional para que no tenga que estar en la URL. A continuación, vuelca $page.

65 lines | src/Controller/VinylController.php
// ... lines 1 - 15
class VinylController extends AbstractController
{
// ... lines 18 - 24
public function homepage(
#[MapQueryParameter] string $query = '',
#[MapQueryParameter] int $page = 1,
): Response
{
dump($query, $page);
// ... lines 31 - 43
}
// ... lines 45 - 63
}

Vale, si añadimos ?page=3 a la URL... no hay sorpresa: vuelca 3. Pero está bien que obtengamos un entero 3: no una cadena. Ahora prueba con page=banana. Un 404! El sistema ve que tenemos un tipo int y realiza la validación.

La función filter_var()

Todo este sistema es manejado por algo llamado QueryParameterValueResolver. Así que si realmente quieres profundizar, comprueba esa clase. Internamente, utiliza una función PHP llamada filter_var() para realizar la validación. No es una función con la que esté muy familiarizado, pero es bastante potente. Le pasas un valor, uno o varios filtros... y te dice si ese valor satisface esos filtros. También puedes pasarle opciones para controlar los filtros.

Si no haces nada extra, el sistema lee nuestra sugerencia de tipo int, y pasa un filtro a filter_var() que exige que sea un int. Por eso falla.

Validar que un int está en un rango

Pero podemos ir más allá. Añade un argumento llamado $limit que por defecto sea 10. Vuelca esto abajo. Pero quiero que el límite esté entre 1 y 10. Para forzarlo, pasa dos opciones especiales a filter_var: min_range puesto a 1 y max_range puesto a 10.

66 lines | src/Controller/VinylController.php
// ... lines 1 - 15
class VinylController extends AbstractController
{
// ... lines 18 - 24
public function homepage(
#[MapQueryParameter] string $query = '',
#[MapQueryParameter] int $page = 1,
#[MapQueryParameter(options: ['min_range' => 1, 'max_range' => 10])] int $limit = 10,
): Response
{
dump($query, $page, $limit);
// ... lines 32 - 44
}
// ... lines 46 - 64
}

¡Vamos a probarlo! Digamos ?limit=3. Funciona como esperamos. Pero cuando probamos limit=13.filter_var() falla y ¡obtenemos un 404! ¡Me encanta!

Obtener parámetros de consulta de matrices

Esto se puede utilizar incluso para manejar matrices. Copia y crea un argumento más: una matriz de $filters que por defecto sea una matriz vacía. Vuelca eso.

67 lines | src/Controller/VinylController.php
// ... lines 1 - 15
class VinylController extends AbstractController
{
// ... lines 18 - 24
public function homepage(
#[MapQueryParameter] string $query = '',
#[MapQueryParameter] int $page = 1,
#[MapQueryParameter(options: ['min_range' => 1, 'max_range' => 10])] int $limit = 10,
#[MapQueryParameter] array $filters = [],
): Response
{
dump($query, $page, $limit, $filters);
// ... lines 33 - 45
}
// ... lines 47 - 65
}

En el navegador, añade ?filters[] igual a plátano, &filters[] igual a manzana. ¡Comprueba ese array en la barra de herramientas de depuración web! También funciona para matrices asociativas: añadefoo y bar entre []. ¡Sí! Una matriz asociativa.

Es una función muy bien diseñada para obtener parámetros de consulta.

Cuerpo de la petición

Además, si necesitas obtener el cuerpo de una petición, en Symfony 6.3 hay un nuevo método llamado $request->getPayload(). ¿Construyendo una API? Cuando tu cliente envíe JSON en el cuerpo, utiliza $request->getPayload() para descodificarlo en una matriz asociativa. ¡Eso está muy bien! Pero además, si tu usuario envía un formulario HTML normal, $request->getPayload() también funciona en ese caso. Detecta que se está enviando un formulario HTML y descodifica los datos de $_POST en una matriz. Así que no importa si estás utilizando una API o un formulario normal, tenemos un método uniforme para obtener la carga útil de la petición. Pequeño, pero bonito.

MapRequestPayload

Hablando de JSON, también es habitual utilizar el serializador para deserializar la carga útil en un objeto. Esto está relacionado con otra nueva función llamada#[MapRequestPayload].

En este caso, __invoke es la acción del controlador. Esto dice: toma el JSON de la petición y deserialízalo en un ProductReviewDto, que es la clase de ejemplo anterior. Después de enviar el JSON a través del serializador, incluso realiza la validación. Así que otra característica bien pensada.

Vale, ¡ya está bien de cosas de peticiones! A continuación, vamos a probar una nueva función de la 6.4: la posibilidad de perfilar comandos de consola.