18. La classe Session

La classe Session

Nous allons maintenant nous occuper de gérer la session courante dans une classe Session.

Eh mais attends, pourquoi on ne gère pas ça de la même façon que $_GET et $_POST, dans la classe Parameter ?

Parce que la session n'est pas gérée de la même manière, tout simplement.

Vous pouvez essayez d'utiliser la classe Parameter, vous verrez que ça risque de coincer et de ne pas fonctionner.

Voici la classe Session qui est plus complète que la classe Parameter (créée dans config) : 

<?php

namespace App\config;

class Session
{
    private $session;

    public function __construct($session)
    {
        $this->session = $session;
    }

    public function set($name, $value)
    {
        $_SESSION[$name] = $value;
    }

    public function get($name)
    {
        if(isset($_SESSION[$name])) {
            return $_SESSION[$name];
        }
    }

    public function show($name)
    {
        if(isset($_SESSION[$name]))
        {
            $key = $this->get($name);
            $this->remove($name);
            return $key;
        }
    }

    public function remove($name)
    {
        unset($_SESSION[$name]);
    }

    public function stop()
    {
        session_destroy();
    }

}

Ouvrez-votre fichier index.php et ajoutez avant l'appel du Router session_start()

<?php

require '../config/dev.php';
require '../vendor/autoload.php';
session_start();
$router = new \App\config\Router();
$router->run();

J'ai aussi mis à jour la classe Request : 

<?php

namespace App\config;

class Request
{
    private $get;
    private $post;
    private $session;

    public function __construct()
    {
        $this->get = new Parameter($_GET);
        $this->post = new Parameter($_POST);
        $this->session = new Session($_SESSION);
    }

    /**
     * @return Parameter
     */
    public function getGet()
    {
        return $this->get;
    }

    /**
     * @return Parameter
     */
    public function getPost()
    {
        return $this->post;
    }

    /**
     * @return Session
     */
    public function getSession()
    {
        return $this->session;
    }
}

Actualisez votre page web, le message d'erreur a disparu 😅.

Oui mais comment je fais pour vérifier que ça fonctionne correctement comme on l'a fait avant avec les deux autres variables superglobales ?

On va ici créer une nouvelle donnée qui sera enregistrée en session pour faire le test. On utilisera ensuite les sessions dès lors qu'on en aura besoin.

Ouvrez votre Router et utilisez un var_dump comme précédemment : 

<?php

namespace App\config;
use App\src\controller\BackController;
use App\src\controller\ErrorController;
use App\src\controller\FrontController;
use Exception;

class Router
{
    private $frontController;
    private $errorController;
    private $backController;
    private $request;

    public function __construct()
    {
        $this->request = new Request();
        $this->frontController = new FrontController();
        $this->backController = new BackController();
        $this->errorController = new ErrorController();
    }

    public function run()
    {
        $this->request->getSession()->set('test', 'value');
        var_dump($this->request->getSession()->get('test'));
        $route = $this->request->getGet()->get('route');
        try{
            if(isset($route))
            {
                if($route === 'article'){
                    $this->frontController->article($this->request->getGet()->get('articleId'));
                }
                elseif ($route === 'addArticle'){
                    $this->backController->addArticle($this->request->getPost());
                }
                else{
                    $this->errorController->errorNotFound();
                }
            }
            else{
                $this->frontController->home();
            }
        }
        catch (Exception $e)
        {
            $this->errorController->errorServer();
        }
    }
}

Actualisez votre page et admirez le résultat... ça fonctionne parfaitement 😊

Supprimez les deux lignes ajoutées dans le Router, on va mettre cela en pratique concrètement.

Vous vous rappelez de l'ajout de l'article qu'on avait mis en place ? On va compléter cette fonctionnalité en affichant un message lors de l'ajout de l'article. 

Une fois la page actualisée, ce message n'apparaîtra plus. 

Oui mais comment je fais pour appeler la Session depuis le BackController ?

 En fait, on ne va pas faire ça, du moins, pas exactement.

Je ne suis pas sûr de bien comprendre ?!?

Ce qu'on va faire, c'est qu'on va faire appel à notre classe Request depuis notre Controller, pour deux raisons évidentes : 

- Request permet d'accéder à la classe Parameter, et à la classe Session

- le fait de les appeler depuis la classe Controller les rendra disponible pour les classes filles

Voici la classe Controller mis à jour : 

<?php

namespace App\src\controller;

use App\config\Request;
use App\src\DAO\ArticleDAO;
use App\src\DAO\CommentDAO;
use App\src\model\View;

abstract class Controller
{
    protected $articleDAO;
    protected $commentDAO;
    protected $view;
    private $request;
    protected $get;
    protected $post;
    protected $session;

    public function __construct()
    {
        $this->articleDAO = new ArticleDAO();
        $this->commentDAO = new CommentDAO();
        $this->view = new View();
        $this->request = new Request();
        $this->get = $this->request->getGet();
        $this->post = $this->request->getPost();
        $this->session = $this->request->getSession();
    }
}

J'ai aussi ajouté des propriétés pour avoir quelques "raccourcis" 😉

Hein ? Qu'est-ce que tu entends par là ? 

Passez dans votre BackController pour ajouter votre message de session : 

<?php

namespace App\src\controller;

use App\config\Parameter;

class BackController extends Controller
{
    public function addArticle(Parameter $post)
    {
        if($post->get('submit')) {
            $this->articleDAO->addArticle($post);
            $this->session->set('add_article', 'Le nouvel article a bien été ajouté');
            header('Location: ../public/index.php');
        }
        return $this->view->render('add_article', [
            'post' => $post
        ]);
    }
}

Et mettez à jour home.php 😉

Mais comment je fais pour récupérer la session dans une vue ?

On va ici faire appel à la classe Request dans View et récupérer la Session 😉

Voici la classe View actualisée :

<?php

namespace App\src\model;

use App\config\Request;

class View
{
    private $file;
    private $title;
    private $request;
    private $session;

    public function __construct()
    {
        $this->request = new Request();
        $this->session = $this->request->getSession();
    }

    public function render($template, $data = [])
    {
        $this->file = '../templates/'.$template.'.php';
        $content  = $this->renderFile($this->file, $data);
        $view = $this->renderFile('../templates/base.php', [
            'title' => $this->title,
            'content' => $content,
            'session' => $this->session
        ]);
        echo $view;
    }

    private function renderFile($file, $data)
    {
        if(file_exists($file)){
            extract($data);
            ob_start();
            require $file;
            return ob_get_clean();
        }
        header('Location: index.php?route=notFound');
    }
}

Et voici home.php actualisé : 

<h1>Mon blog</h1>
<p>En construction</p>
<?= $this->session->show('add_article'); ?>
<a href="../public/index.php?route=addArticle">Nouvel article</a>
<?php
foreach ($articles as $article)
{
    ?>
    <div>
        <h2><a href="../public/index.php?route=article&articleId=<?= htmlspecialchars($article->getId());?>"><?= htmlspecialchars($article->getTitle());?></a></h2>
        <p><?= htmlspecialchars($article->getContent());?></p>
        <p><?= htmlspecialchars($article->getAuthor());?></p>
        <p>Créé le : <?= htmlspecialchars($article->getCreatedAt());?></p>
    </div>
    <br>
    <?php
}
?>

Si vous essayez d'ajouter un nouvel article, cela fonctionne toujours, on a maintenant le message qui s'affiche.

Et lorsque vous actualisez votre page, le message disparaît 😊

Passons maintenant à la modification d'un article.

 

Bilan

Dans ce chapitre, nous avons mis en place une classe Session pour gérer la session utilisateur au format objet.

Vous pouvez retrouver le code associé à ce chapitre sur GitHub.