Sesiones


1Presentación

El sistema de sesiones permite el almacenamiento temporal de variables vinculadas a un visitante. La ventaja es poder realizar un procesamiento en un controlador en función del procesamiento realizado previamente en los controladores ejecutados con anterioridad.
Cada sesión está vinculada a un navegador mediante una cookie colocada en el primer acceso. Esto es transparente porque lo gestiona el framework.

El objeto de gestión de sesiones es creado automáticamente por Temma, si la configuración así lo prevé.


2Configuración

En el archivo etc/temma.php, puedes definir cómo se almacenan las sesiones (consulta la documentación de configuración).

Ten en cuenta que si no se especifica ninguna fuente, Temma usa el mecanismo de sesiones nativo de PHP. Ten en cuenta que PHP almacena los datos de sesión en archivos, que se bloquean al acceder a ellos. Esto significa que solo una solicitud puede acceder a ellos a la vez, lo que puede provocar bloqueos si tienes solicitudes de larga duración (por ejemplo, si usas controladores de eventos).


3Objeto de sesión

En los controladores, el objeto de sesión está disponible escribiendo:

$this->_session

En los demás objetos gestionados por el componente de inyección de dependencias, se puede acceder al objeto de sesión escribiendo:

$this->_loader->session

4Lectura de datos

Para leer datos de la sesión, basta con usar el objeto como un array asociativo:

$currentUser = $this->_session['user'];

Para saber si una variable de sesión existe, o si está vacía:

// ¿está definida la variable?
if (isset($this->_session['myVariable']))
    doSomething();

// ¿está vacía la variable?
if (empty($this->_session['myOtherVariable']))
    doSomethingElse();

// variable no definida: usa un valor por defecto
$var = $this->_session['myVariable'] ?? 'defaultValue';

// variable no definida o vacía: usa un valor por defecto
$var = $this->_session['myVariable'] ?: 'defaultValue';

Con el método get(), puedes leer una variable de sesión, especificando un valor por defecto que se devuelve si el dato no está presente en la sesión:

$var = $this->_session->get('myVariable', 'Default value');

Es posible recuperar todas las variables de sesión con el método getAll():

$sessVariables = $this->_session->getAll();
$currentUser = $sessVariables['user'];
$basket = $sessVariables['basket'];

También es posible recuperar todas las variables de sesión cuyo nombre comienza con un determinado prefijo, usando el método getPrefix():

$names = $this->_session->getPrefix('name-');

foreach ($names as $nameKey => $nameValue) {
    print($nameKey . ' : ' . $nameValue);
}
/*
 * Por ejemplo, podría mostrar:
 * name-1 : Alice
 * name-2 : Bob
 * name-3 : Camille
 */

print($this->_session['name-1']);
// escribe "Alice"

5Escritura de datos

Para crear o modificar una variable de sesión:

$this->_session['myVariable'] = $value;

Si el valor asignado a la variable es null, la variable se elimina de la sesión.

Para leer y escribir datos, el objeto de gestión de sesiones se usa como un array. Pero esto no permite escribir valores directamente en arrays multidimensionales.
Para modificar un array multidimensional, primero debes recuperar el array completo, modificarlo y luego sobrescribir la variable de sesión:

// esto no funciona
$this->_session['user']['name'] = 'Einstein';

// así es como se hace
$user = $this->_session['user'];
$user['name'] = 'Einstein';
$this->_session['user'] = $user;

6Eliminación de datos

Para destruir una variable de sesión:

unset($this->_session['myVariable']);

Para eliminar todas las variables de la sesión:

$this->_session->clean();

7Extracción de datos

La extracción de datos consiste en leer las variables de sesión y luego eliminarlas de la sesión.

Es posible extraer datos de la sesión, es decir, leerlos y eliminarlos de la sesión en una sola llamada al método extract():

$value = $this->_session->extract('myVariable');

// es equivalente a
$value = $this->_session['myVariable'];
unset($this->_session['myVariable']);

// extract() también puede recibir un valor por defecto
$value = $this->_session->extract('myVariable', 'default value');

También puedes extraer todas las variables de sesión cuyos nombres comienzan con un determinado prefijo. Las variables recuperadas se eliminan de la sesión. Para ello, usa el método extractPrefix():

$users = $this->_session->extractPrefix('user-');

foreach ($users as $login => $name) {
    print("$login : $name");
}
/*
 * Por ejemplo, podría mostrar:
 * jrambo : John Rambo
 * jconnor : John Connor
 * jwick : John Wick
 */

8Variables flash

8.1Principio

Las variables flash son variables de sesión con una vida útil muy limitada. La próxima vez que se cargue una página, se extraen (y por tanto se eliminan) de la sesión, y se ponen a disposición en variables de plantilla.

Para convertir una variable de sesión en una variable flash, basta con anteponer a su nombre dos guiones bajos (__).


8.2Ejemplo 1

Imaginemos un controlador Article con tres acciones:

  • view: Muestra el contenido de un artículo, según su identificador pasado como parámetro. Si el artículo no existe, la acción redirige a /article/info, tras haber creado previamente la variable flash __status con el valor unknown_article.
  • list: Muestra la lista de artículos. Si no existe ningún elemento, la acción redirige a /article/info, tras haber creado previamente la variable flash __status con el valor empty_list.
  • info: muestra un mensaje de error, según el valor de la variable flash __status.

Aquí está el archivo controllers/Article.php:

<?php

/** Controlador de gestión de artículos. */
class Article extends \Temma\Web\Controller {
    /** Acción que muestra un artículo según su identificador. */
    public function view(int $articleId) {
        // recupera el artículo
        $article = ...
        // comprueba el artículo
        if (!$article) {
            // crea la variable flash
            $this->_session['__status'] = 'unknown_article';
            // redirige
            return $this->_redirect('/article/info');
        }
    }
    /** Acción que muestra la lista de artículos. */
    public function list() {
        // recupera los artículos
        $articles = ...
        // comprueba los artículos
        if (!$articles) {
            // crea la variable flash
            $this->_session['__status'] = 'empty_list';
            // redirige
            return $this->_redirect('/article/info');
        }
    }
    /** Acción que muestra información. */
    public function info() {
        // sin procesamiento
    }
}
  • Línea 8: recuperación del artículo por identificador.
  • Líneas 10 a 15: procesamiento cuando no existe ningún artículo con este identificador.
    • Línea 12: creación de la variable flash.
    • Línea 14: redirección.
  • Línea 20: recuperación de la lista de artículos.
  • Líneas 22 a 27: procesamiento cuando no hay artículos.
    • Línea 24: creación de la variable flash.
    • Línea 26: redirección.

Aquí está el archivo templates/article/info.tpl:

<html>
<body>

    <h1>Información</h1>
    {* muestra un mensaje según la variable flash *}
    {if $__status == 'unknown_article'}
        El artículo solicitado no existe.
    {elseif $__status == 'empty_list'}
        No hay artículos que mostrar.
    {else}
        Se ha producido un error.
    {/if}

</body>
</html>

8.3Ejemplo 2

En este segundo ejemplo, vamos a hacer evolucionar el controlador Article. Cuando la acción view encuentra un error (el artículo no existe), redirige a la acción list, para mostrar la lista de artículos.

La acción list sigue redirigiendo a info si no tiene elementos que mostrar. En cambio, si fuiste redirigido desde la acción view, es el estado de esta última (unknown_article) el que se propaga, y no el que indica que no hay artículos (empty_list).

Aquí está el archivo controllers/Article.php:

<?php

/** Controlador de gestión de artículos. */
class Article extends \Temma\Web\Controller {
    /** Acción que muestra un artículo según su identificador. */
    public function view(int $articleId) {
        // recupera el artículo
        $article = ...
        // comprueba el artículo
        if (!$article) {
            // crea la variable flash
            $this->_session['__status'] = 'unknown_article';
            // redirige
            return $this->_redirect('/article/info');
        }
    }
    /** Acción que muestra la lista de artículos. */
    public function list() {
        // recupera los artículos
        $articles = ...
        // comprueba los artículos
        if (!$articles) {
            // crea la variable flash
            if ($this['__status'])
                $this->_session['__status'] = $this['__status'];
            else
                $this->_session['__status'] = 'empty_list';
            // redirige
            return $this->_redirect('/article/info');
        }
    }
    /** Acción que muestra información. */
    public function info() {
        // sin procesamiento
    }
}

Líneas 22 a 30: procesamiento cuando no hay elementos.

  • Línea 24: Comprueba si la variable de plantilla __status existe y no está vacía. Si es así, se ha definido una variable flash __status en la página anterior.
  • Línea 25: si la variable de plantilla __status existe y no está vacía, usa su valor para crear una nueva variable flash __status.
  • Línea 27: en caso contrario, crea una variable flash con el valor empty_list.
  • Línea 29: redirección.