Aquí traigo otro minitutorial sobre Symfony. Siguiendo con los tutoriales de iniciación a Symfony, llegamos a las variables de sesión. Es decir, en este post trato de explicar cómo en Symfony podemos gestionar las visitas individualmente, identificando a los usuarios que visitan una web, personalizando los contenidos o mensajes aún más que les mostraremos.
Es decir, al poder seguir las sesiones de los usuarios, podemos estar seguros de quién es el que está viendo cierta sección. Así podremos mostrarle los contenidos que le corresponden, personalizando y adecuando los contenidos mejor. En estas sesiones podremos almacenar variables o mensajes. Es decir, estas sesiones son unos espacios individuales para cada usuario en donde podremos almacenar dichas variables. Además de que Symfony te añade una utilidad muy práctica que son las bolsas de mensajes flash.
Todo comienza cuando recién llega un usuario a la web. Symfony lo identifica como usuario anónimo, y también queda identificado unívocamente aunque sea anónimo. Así luego podremos guardar variables asociadas a cada usuario, cada vez que abra un usuario una sesión, incluso si se trata de un usuario anónimo.
Para seguir con el post puedes bajarte antes el código fuente:
https://github.com/jaimenj/symfony-starter-tutorials
Un poco de teoría sobre las sesiones y las bolsas de Symfony
A saber, un usuario es un navegador, y en cada navegador se abre una sesión en la primera visita que hace a la web. Si abrimos dos navegadores distintos, o navegamos de incógnito, serán sesiones distintas. Debemos también permitir las cookies, sino Symfony no sabrá si es el mismo visitante que vuelve a pedir otra página o no.
Otra cosa es una sesión, y una vez se haya hecho login, se autentica a un usuario, pero independientemente un usuario autenticado puede tener varias sesiones abiertas en varios navegadores distintos. Esto va complicando la explicación, ya lo sé. Pero realmente es así el funcionamiento, y es importante no pensar que un usuario es una sesión, ya que un mismo usuario puede haber abierto varias sesiones en varios navegadores y ordenadores simultáneamente.
Lo último es tener en cuenta para este tema, es que cada visita es una sesión. Y para cada sesión, Symfony abre una bolsa en donde se encapsulan todas las variables que queramos. Cuando haya expirado el tiempo de inactividad, la sesión se cerrará. Incluso si el usuario es recordado, se abrirán una nueva sesión cuando vuelva.
Para qué son las variables de sesión
Estas sesiones se almacenan en el servidor, y con éstas podemos hacer cosas como llevar un carrito de la compra único para cada usuario. Mostrarle mensajes de vuelta del servidor, después de haber enviado un formulario con los resultados de guardarlo. Y un largo etcétera..
Sin el seguimiento de la sesión de un usuario, ninguna web sabría quién es el que está visitando una página web. Serían imposibles la gran mayoría de las acciones que llevamos a cabo en las webs. Sin el seguimiento de las sesiones, lo único posible sería ver contenidos informátivos de carácter general, para todos los usuarios.
El codekata con proyecto para las pruebas
Para esto, podemos ir a línea de comandos y poner:
symfony new symfony-tutorial-17
cd symfony-tutorial-17
composer require --dev profiler maker
composer require twig annotations
Lo siguiente es generar un controlador para hacer las pruebas:
php bin/console make:controller DefaultController
Lo edito para que cargue desde la página de inicio, ya que si no cargará desde /default por su nombre. Para esto hay que cambiar en el fichero del controlador de:
* @Route("/default", name="default")
A:
* @Route("/", name="default")
Arrancamos en local con:
symfony server:start
Y si todo a ido bien ya tenemos el proyecto local de pruebas en: http://localhost:8000/
Cómo guardar variables nuevas en una sesión
Ahora bien, imaginemos que queremos guardar la localización aproximada de un usuario que nos visita. Ya lo hemos localizado con alguna herramienta, y simplemente queremos guardar el dato en su bolsa de sesión, no en la base de datos. En el controlador podemos hacer:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends AbstractController
{
/**
* @Route("/", name="default")
*/
public function index(Request $request)
{
$session = $request->getSession();
$session->set('city', 'Nombre de la ciudad');
$session->set('country_name', 'Nombre del país');
$session->set('latitude', 0.123);
$session->set('longitude', 0.123);
return $this->render('default/index.html.twig', [
'controller_name' => 'DefaultController',
]);
}
}
Cómo utilizar variables de sesión
Esto es más sencillo todavía porque simplemente así las podemos consultar de nuevo en otro controlador:
$detectedLatitude = $session->get('latitude');
En una plantilla de Twig podemos hacer algo tal que así:
{{ app.session.get('city') }}, {{ app.session.get('country_name') }}
..que pintaría la ciudad y país detectados o almacenados previamente en la bolsa del usuario que nos visita. Todo junto en otra entrada del mismo controlador podría quedar así:
/**
* @Route("/show-session-variables", name="show")
*/
public function show(Request $request)
{
$detectedLatitude = $request->getSession()->get('latitude');
return $this->render('default/show.html.twig', [
'controller_name' => 'DefaultController',
'detected_latitude' => $detectedLatitude,
]);
}
Ahora si visitamos primero la URL: http://localhost:8000/show-session-variables
Y luego la URL nueva: http://localhost:8000/show-session-variables
Veremos cómo se guardan datos en la primera visita, se almacenan, y se visualizan después. Esto es muy últil por ejemplos para construir los carritos de la compra online.
Los mensajes flash de Symfony
Por último, con respecto a la sesiones, tenemos una utilidad muy buena de Symfony para los clásicos mensajes de usuario. Son los llamados mensajes flash. Que se destinan de forma clásica a mostrar mensajes. Y una vez consumidos se borran de la bolsa.
Estos mensajes tendrán una categoría y un texto descriptivo, pudiendo poner lo que queramos. Para guardar mensajes flash en la bolsa podemos hacer lo siguiente en los controladores:
$this->addFlash('danger', 'ERROR: No podemos modificar la contraseña porque no coinciden.');
$this->addFlash('success', 'Datos guardados.');
$this->addFlash('warning', 'Ha ocurrido algo alarmante.');
Tanto en la categoría (1er parámetro), como en la descripción (2do parámetro), podemos poner lo que queramos. Luego podemos mostrarle al usuario en la plantilla dichos mensajes y consumirlos. Para mostrarlos podemos hacer algo como lo siguiente, que construí para un proyecto usando estilos de Bootstrap y la caja de mensajes cerrable:
{% for label, messages in app.flashes %}
{% for message in messages %}
<div class="alert alert-{{ label }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endfor %}
{% endfor %}
..esto te muestra una caja con una X con la que puedes cerrar el mensaje. Pero para que sea compatible con Bootstrap tienes que usar las categorías de Bootstrap que son: warning, success, danger, info..
Si esto lo añadimos con un poco de Bootstrap en las plantillas, debería de verse algo parecido a lo siguiente:
Terminando
Para terminar con este post de la serie de iniciación, sólo me queda remitirme a la documentación oficial:
https://symfony.com/doc/current/components/http_foundation/sessions.html
Aquí los códigos fuentes de este post 17:
https://github.com/jaimenj/symfony-starter-tutorials