Login to bookmark this video
Buy Access to Course
11.

Enviar un formulario mediante GET

|

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

Ahora tenemos un formulario de búsqueda. Pero hay un pequeño problema. Se envía a través de POST porque es el método por defecto de Symfony. Normalmente, eso está muy bien. Pero para un formulario de búsqueda, POST no es la mejor opción. ¿Por qué? Porque cuando buscamos, queremos que la consulta sea visible en la URL. Hace que los resultados de la página se puedan compartir y marcar como favoritos. Además, es como nuestro antiguo formulario. Así que vamos a modificarlo y cambiar nuestro formulario a GET.

Para empezar, abre nuestra clase PartSearchType. En setDefaults()podemos ajustar las opciones de nuestro formulario. En la matriz vacía, añade una nueva clave llamadamethod y establécela en Request::METHOD_GET. En realidad, es sólo una forma rara de escribir la cadena GET:

33 lines | src/Form/PartSearchType.php
// ... lines 1 - 6
use Symfony\Component\HttpFoundation\Request;
// ... lines 8 - 9
class PartSearchType extends AbstractType
{
// ... lines 12 - 24
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
// Configure your form options here
'method' => Request::METHOD_GET,
]);
}
}

Tómate un momento para enviar el nuevo formulario con "Legacy". Fíjate en la URL. Los parámetros de consulta parecen un poco locos. En lugar del simple query=legacy, vemos parts_search[query]=legacy - esos %5B y %5D's son simplemente [] codificados .

¿Qué ocurre? Por defecto, los formularios Symfony envían los datos como matrices anidadas, con la clave del nombre del formulario. Esto ayuda a evitar colisiones de nombres cuando tienes varios formularios en la misma página. Es un movimiento inteligente, pero para nuestro formulario de búsqueda, es exagerado y, seamos sinceros, un poco feo.

Limpiar los parámetros de consulta

Esto es lo que haremos. Queremos aplanar los parámetros de consulta. Para deshacernos de este prefijo de nombre de formulario, podemos anular un método especial en el tipo de formulario.

De vuelta en PartSearchType, al final de esta clase, pulsaréCmd + N y elegiré "Anular métodos", luego elegiré el método getBlockPrefix(). Dentro de él, simplemente devuelve una cadena vacía:

38 lines | src/Form/PartSearchType.php
// ... lines 1 - 9
class PartSearchType extends AbstractType
{
// ... lines 12 - 32
public function getBlockPrefix(): string
{
return '';
}
}

Esto le dice a Symfony que no anteponga a nuestros campos el nombre del formulario. Vuelve a buscar y ¡bam! Tenemos parámetros de consulta limpios y planos. ¡Mucho mejor!

Pero aún no hemos llegado al final. Tenemos esta consulta _token en la URL. Es la protección CSRF haciendo su trabajo, pero es innecesaria para un formulario de búsqueda basado en GET. Sólo estamos filtrando una lista de productos, así que vamos a desactivarla para este formulario en setDefaults().

Para ello, vuelve a PartSearchType y añade una nueva opción llamadacsrf_protection, estableciéndola en false:

39 lines | src/Form/PartSearchType.php
// ... lines 1 - 9
class PartSearchType extends AbstractType
{
// ... lines 12 - 24
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
// ... lines 28 - 29
'csrf_protection' => false,
]);
}
// ... lines 33 - 37
}

Vuelve a enviar el formulario y ¡bingo! Sólo tenemos el parámetro query en la URL, limpia e intencionadamente.

Hacer que el campo de búsqueda sea opcional

¿Qué pasa si intentamos enviar el formulario con una consulta vacía? Hmm, un error de validación HTML5... Puede que eso esté bien para tu aplicación, pero yo preferiría que una búsqueda vacía significara "Muéstramelo todo". Podemos desactivar la validación utilizando el atributo novalidateen la etiqueta del formulario, pero una opción mejor es simplemente hacer que el campo sea opcional. Para el campo query, añade otro parámetro llamado requiredy ajústalo a false:

40 lines | src/Form/PartSearchType.php
// ... lines 1 - 9
class PartSearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('query', null, [
'required' => false,
// ... lines 17 - 21
])
;
}
// ... lines 25 - 38
}

Actualiza la página, y si intentamos buscar con una entrada vacía, simplemente muestra la lista completa.

Sinceramente, ahora mismo, la búsqueda funciona debido a cierta lógica de negocio heredada en PartController. Concretamente, estamos obteniendo la consulta directamente de la petición con $request->query->getString('query'):

28 lines | src/Controller/PartController.php
// ... lines 1 - 11
final class PartController extends AbstractController
{
// ... line 14
public function index(StarshipPartRepository $repository, Request $request,): Response
{
// ... line 17
$query = $request->query->getString('query');
// ... lines 19 - 25
}
}

Y para un pequeño formulario de búsqueda, eso está totalmente bien. Pero ya que estamos aprendiendo el componente Formulario de Symfony, hagámoslo a la manera de Symfony.

Manejo adecuado de formularios en Symfony

Comenta esa línea. A continuación, inicializa una nueva variable query con el valor null. A continuación, dile al formulario que gestione la petición con$searchForm->handleRequest($request):

33 lines | src/Controller/PartController.php
// ... lines 1 - 11
final class PartController extends AbstractController
{
// ... line 14
public function index(StarshipPartRepository $repository, Request $request,): Response
{
// ... line 17
//$query = $request->query->getString('query');
$query = null;
$searchForm->handleRequest($request);
// ... lines 21 - 30
}
}

Añade nuestra comprobación habitual de envío de formularios. if ($searchForm->isSubmitted()&& $searchForm->isValid()) . El campo query se considera no mapeado porque el formulario no está asociado a un objeto. Dentro de if, establece la variable$query en $searchForm->get('query')->getData():

33 lines | src/Controller/PartController.php
// ... lines 1 - 11
final class PartController extends AbstractController
{
// ... line 14
public function index(StarshipPartRepository $repository, Request $request,): Response
{
// ... line 17
//$query = $request->query->getString('query');
$query = null;
$searchForm->handleRequest($request);
if ($searchForm->isSubmitted() && $searchForm->isValid()) {
$query = $searchForm->get('query')->getData();
}
// ... lines 24 - 30
}
}

Esto captura el campo de consulta y recupera su valor enviado.

Tip

Para obtener todos los datos del formulario a la vez, como una matriz, puedes utilizar$searchForm->getData().

Toques finales y potencia turbo

Ya casi está. Hagamos el último retoque en la plantilla. Copia el icono SVG y colócalo debajo de todo el formulario. El posicionamiento CSS adecuado debería seguir funcionando, así que no necesitamos colocarlo entre las etiquetas de apertura y cierre del formulario. Ahora ya podemos eliminar por completo el antiguo formulario:

41 lines | templates/part/index.html.twig
// ... lines 1 - 4
{% block body %}
<div class="flex justify-end mt-6 mb-6">
<div class="relative w-full max-w-md">
{{ form(searchForm) }}
<svg class="absolute left-3 top-3 w-5 h-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-4.35-4.35m0 0A8.5 8.5 0 1011 19.5a8.5 8.5 0 005.65-2.85z" />
</svg>
</div>
</div>
// ... lines 15 - 39
{% endblock %}

Actualiza la página de nuevo para ver nuestro formulario, y si lo buscamos, ¡todavía funciona! Tiene el mismo aspecto, pero ahora funciona completamente con Symfony Forms.

De vuelta en PartSearchType.php, una última mejora. Por defecto, si no especificas el tipo de campo, Symfony utiliza TextType. Pero como se trata de un campo de búsqueda, seamos un poco más semánticos y cambiémoslo por uno especial SearchType:

41 lines | src/Form/PartSearchType.php
// ... lines 1 - 5
use Symfony\Component\Form\Extension\Core\Type\SearchType;
// ... lines 7 - 10
class PartSearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('query', SearchType::class, [
// ... lines 17 - 23
;
}
// ... lines 26 - 39
}

De vuelta en el navegador, actualiza de nuevo la página. A primera vista no ha cambiado nada, pero si empiezas a escribir, hay un pequeño y práctico botón X que te permite borrar fácilmente la entrada.

Activar Turbo en el sitio web

Si recuerdas, desactivé Turbo al principio de este curso para simplificar las cosas. Pero ahora es el momento de desatar su poder. Abre assets/app.js y descomenta import '@hotwired/turbo';:

13 lines | assets/app.js
// ... line 1
// import '@hotwired/turbo';
// ... lines 3 - 13

Ahora, la navegación por el sitio se realiza mediante AJAX con Turbo. Puedes verlo en acción en la barra de herramientas de depuración web al hacer clic en los enlaces. El envío de formularios también se realiza mediante Turbo, y los errores de formulario siguen funcionando perfectamente.

En la lista de piezas, si vas a "Crear nueva pieza" e intentas enviar el formulario vacío... Sí, es una petición AJAX y seguimos viendo los errores de validación esperados. Turbo hace que nuestra aplicación sea más rápida, fluida e inmersiva. ¡Y esto es sólo el principio!

Go Deeper!

Si quieres profundizar más, te recomiendo que eches un vistazo a nuestro [curso Turbo] independiente (https://symfonycasts.com/screencast/turbo).

Para terminar

¡Muy bien, amigos! Ya dominas oficialmente los fundamentos del componente Formulario de Symfony. Ya sabes cómo instalarlo y configurarlo, crear tipos de formularios, procesarlos con las funciones de ayuda de Twig y gestionar los envíos correctamente con Form::handleRequest(). Hemos visto cómo se enlazan los formularios con las entidades Doctrine, cómo funciona la validación, cómo personalizar los campos y atributos, y cómo dar estilo a todo con los temas de formulario Symfony incorporados.

Estamos listos para construir formularios reales, listos para producción, con confianza. Así que, ¡a construir formularios increíbles! Son esenciales en tus aplicaciones. Y disfruta de la magia de los formularios Symfony.

hasta la próxima, ¡feliz programación!