Sessions


1Présentation

Le système de session permet de stocker temporairement des variables, qui sont liées à un visiteur. L'intérêt est de faire des traitements dans un contrôleur en fonction des traitements effectuée précédemment dans les contrôleurs exécutés préalablement.
Chaque session est liée à un navigateur par le biais d'un cookie déposé au premier accès. Cela est transparent car géré par le framework.

L'objet de gestion des sessions est créé automatiquement par Temma, si la configuration le prévoit.


2Configuration

Dans le fichier etc/temma.php, il est possible de définir la manière dont les sessions sont stockées (voir la documentation de la configuration).

Attention, si aucune source n'est spécifiée, Temma utilise le mécanisme de sessions natif de PHP. Il faut savoir que PHP stocke les données de session dans des fichiers, qui sont verrouillés lors de leur accès. Donc une seule requête peut y accéder à la fois, ce qui peut créer des verrouillages si vous avez des requêtes qui durent longtemps (par exemple si vous utilisez des contrôleurs d'événements).


3Objet Session

Dans les contrôleurs, l'objet de session est disponible en écrivant :

$this->_session

Dans les autres objets gérés par le composant d'injection de dépendances, l'objet de session est accessible en écrivant :

$this->_loader->session

4Lecture de données

Pour lire des données depuis la session, il suffit d'utiliser l'objet comme un tableau associatif :

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

Pour savoir si une variable de session existe, ou si elle est vide :

// est-ce que la variable est définie ?
if (isset($this->_session['myVariable']))
    doSomething();

// est-ce que la variable est vide ?
if (empty($this->_session['myOtherVariable']))
    doSomethingElse();

// variable non définie : utilisation d'une valeur par défaut
$var = $this->_session['myVariable'] ?? 'defaultValue';

// variable non définie ou vide : valeur par défaut
$var = $this->_session['myVariable'] ?: 'defaultValue';

Avec la méthode get(), il est possible de lire une variable de session, en spécifiant une valeur par défaut qui est retournée si la donnée n'est pas présente en session :

$var = $this->_session->get('myVariable', 'Valeur par défaut');

Il est possible de récupérer toutes les variables de session avec la méthode getAll() :

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

Il est aussi possible de récupérer toutes les variable de session dont le nom commence par un certain préfixe, avec la méthode getPrefix() :

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

foreach ($names as $nameKey => $nameValue) {
    print($nameKey . ' : ' . $nameValue);
}
/*
 * Pourrait afficher par exemple :
 * name-1 : Alice
 * name-2 : Bob
 * name-3 : Camille
 */

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

5Écriture de données

Pour créer ou modifier une variable de session :

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

Si la valeur assignée à la variable vaut null, la variable est effacée de la session.

Pour lire et écrire des données, l'objet de gestion des sessions s'utilise comme un tableau. Mais cela ne permet pas d'écrire directement des valeurs sur des tableaux multi-dimensionnels.
Pour modifier un tableau multi-dimensionnel, il faut donc commencer par récupérer le tableau complet, le modifier, puis écraser la variable de session :

// cela ne fonctionne pas
$this->_session['user']['name'] = 'Einstein';

// il faut procéder ainsi
$user = $this->_session['user'];
$user['name'] = 'Einstein';
$this->_session['user'] = $user;

6Effacement de données

Pour détruire une variable de session :

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

Pour effacer toutes les variables de la session :

$this->_session->clean();

7Extraction de données

L'extraction de données consiste en la lecture de variables de session tout les en effaçant de la session.

Vous pouvez extraire un donnée de la session, c'est à dire la lire et l'effacer de la session en un seul appel à la méthode extract() :

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

// est équivalent à
$value = $this->_session['myVariable'];
unset($this->_session['myVariable']);

// extract() peut aussi prendre une valeur par défaut
$value = $this->_session->extract('myVariable', 'default value');

Vous pouvez aussi extraire toutes les variables de session dont le nom commence par un certain préfixe. Les variables récupérées sont effacées de la session. Pour cela, il faut utiliser la méthode extractPrefix() :

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

foreach ($users as $login => $name) {
    print("$login : $name");
}
/*
 * Pourrait afficher par exemple :
 * jrambo : John Rambo
 * jconnor : John Connor
 * jwick : John Wick
 */

8Variables flash

8.1Principe

Les variables flash sont des variables de session qui ont une durée de vie très limitée. Au prochain chargement de page, elles sont extraites (et donc effacées) de la session, et mises à disposition dans les variables de template.

Pour qu'une variable de session soit une variable flash, il suffit de préfixer son nom avec deux underscores (__).


8.2Exemple 1

Imaginons un contrôleur Article, qui possède trois actions :

  • voir : Affiche le contenu d'un article, à partir de son identifiant passé en paramètre. Si l'article n'existe pas, l'action redirige vers /article/info en ayant d'abord créé la variable flash __statut avec la valeur article_inconnu.
  • liste : Affiche la liste des articles. Si aucun article n'existe, l'action redirige vers /article/info en ayant d'abord créé la variable flash __statut avec la valeur liste_vide.
  • info : affiche un message d'erreur, en fonction de la valeur de la variable flash __statut.

Fichier controllers/Article.php :

<?php

/** Contrôleur de gestion des articles. */
class Article extends \Temma\Web\Controller {
    /** Action qui affiche un article à partir de son identifiant. */
    public function voir(int $articleId) {
        // récupération de l'article
        $article = ...
        // vérification de l'article
        if (!$article) {
            // création de la variable flash
            $this->_session['__statut'] = 'article_inconnu';
            // redirection
            return $this->_redirect('/article/info');
        }
    }
    /** Action qui affiche la liste des articles. */
    public function liste() {
        // récupération des articles
        $articles = ...
        // vérification de la présence d'articles
        if (!$articles) {
            // création de la variable flash
            $this->_session['__statut'] = 'liste_vide';
            // redirection
            return $this->_redirect('/article/info');
        }
    }
    /** Action qui affiche des informations. */
    public function info() {
        // aucun traitement
    }
}
  • Ligne 8 : récupération de l'article à partir de son identifiant.
  • Lignes 10 à 15 : traitement lorsqu'il n'y a pas d'article avec cet identifiant.
    • Ligne 12 : création de la variable flash.
    • Ligne 14 : redirection.
  • Ligne 20 : récupération de la liste des articles.
  • Lignes 22 à 27 : traitement lorsqu'il y a aucun article.
    • Ligne 24 : création de la variable flash.
    • Ligne 26 : redirection.

Fichier templates/article/info.tpl :

<html>
<body>

    <h1>Informations</h1>
    {* affiche un message en fonction de la variable flash *}
    {if $__statut == 'article_inconnu'}
        L'article demandé n'existe pas.
    {elseif $__statut == 'liste_vide'}
        Il n'y a pas d'article à afficher.
    {else}
        Une erreur a été rencontrée.
    {/if}

</body>
</html>

8.3Exemple 2

Dans ce deuxième exemple, on va faire évoluer le contrôleur Article. Lorsque l'action voir rencontre une erreur (l'article n'existe pas), elle redirige vers l'action liste, pour afficher la liste des articles.

L'action liste, continue à rediriger vers info si elle n'a pas d'articles à afficher. Par contre, si on avait été redirigé depuis l'action voir, c'est le statut de cette dernière (article_inconnu) qui est propagé, et non pas celui indiquant qu'il n'y a aucun article (liste_vide).

Fichier controllers/Article.php :

<?php

/** Contrôleur de gestion des articles. */
class Article extends \Temma\Web\Controller {
    /** Action qui affiche un article à partir de son identifiant. */
    public function voir(int $articleId) {
        // récupération de l'article
        $article = ...
        // vérification de l'article
        if (!$article) {
            // création de la variable flash
            $this->_session['__statut'] = 'article_inconnu';
            // redirection
            return $this->_redirect('/article/info');
        }
    }
    /** Action qui affiche la liste des articles. */
    public function liste() {
        // récupération des articles
        $articles = ...
        // vérification de la présence d'articles
        if (!$articles) {
            // création de la variable flash
            if ($this['__status'])
                $this->_session['__statut'] = $this['__statut'];
            else
                $this->_session['__statut'] = 'liste_vide';
            // redirection
            return $this->_redirect('/article/info');
        }
    }
    /** Action qui affiche des informations. */
    public function info() {
        // aucun traitement
    }
}

Lignes 22 à 30 : traitement lorsqu'il n'y a aucun article.

  • Ligne 24 : On regarde si la variable de template __statut existe et n'est pas vide. Si c'est le cas, c'est qu'une variable flash __statut a été définie sur la page précédente.
  • Ligne 25 : si la variable de template __statut existe et n'est pas vide, on utilise sa valeur pour créer une nouvelle variable flash __statut.
  • Ligne 27 : sinon, on crée une variable flash en lui donnant la valeur liste_vide.
  • Ligne 29 : redirection.