17. La classe Request

La classe Request

On va maintenant créer une nouvelle classe, Request, qui va nous permettre de gérer la requête. Cette dernière va contenir les variables superglobales :

- $_GET

- $_POST

- $_SESSION

En fait, tu veux simplifier notre Router c'est ça ? 😒

Pas uniquement, cette classe sera utilisée à plusieurs endroits dans notre application 

Voici notre classe Request (à créer dans le dossier config): 

  

<?php

namespace App\config;

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

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

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

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

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

Il nous reste à l'intégrer à l'application existante 😉

Ouvrez votre fichier Router.php et Ajoutez l'appel à la classe Request dans le constructeur, ajoutez un var_dump au tout début de la méthode run pour voir ce que contient cet objet :

<?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()
    {
        var_dump($this->request);
        try{
            if(isset($_GET['route']))
            {
                if($_GET['route'] === 'article'){
                    $this->frontController->article($_GET['articleId']);
                }
                elseif ($_GET['route'] === 'addArticle'){
                    $this->backController->addArticle($_POST);
                }
                else{
                    $this->errorController->errorNotFound();
                }
            }
            else{
                $this->frontController->home();
            }
        }
        catch (Exception $e)
        {
            $this->errorController->errorServer();
        }
    }
}

Actualisez votre page web et... 😱


On a une erreur qui s'affiche et le contenu du var_dump est nul  😔

Ok, on va pour le moment laisser de côté l'erreur qui s'affiche, on va essayer de s'occuper des informations dans le var_dump pour commencer.

Commençons par l'attribut get. Il est vide sur cette page, mais si vous allez visualiser un article ou d'en ajouter un nouveau, il affiche bien les informations en conséquence comme ici : 


Ok, je vois, mais comment je fais pour récupérer uniquement la route par exemple ? 

Il vous suffit de faire à la place du var_dump actuel ceci :

<?php

var_dump($this->request->getGet()['route']);
Oui je vois, mais on peut rendre ça plus "objet" ?

Bien sûr, commencez par créer une nouvelle classe : la classe Parameter (dans le dossier config). 

Voici la classe Parameter, tout ce qu'il y a de plus simple, avec une propriété, un constructeur, un getter et un setter :

<?php

namespace App\config;

class Parameter
{
    private $parameter;

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

    public function get($name)
    {
        if(isset($this->parameter[$name]))
        {
            return $this->parameter[$name];
        }
    }
    
    public function set($name, $value)
    {
        $this->parameter[$name] = $value;
    }

}
Ok, mais j'en fais quoi de cette classe maintenant ?

Eh bien, on y fait appel depuis notre classe Request 😉

<?php

namespace App\config;

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

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

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

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

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

Pensez à modifier votre var_dump comme ci-dessous : 

<?php

var_dump($this->request->getGet()->get('route'));

Actualisez votre page web et... ça fonctionne 😉

Pour ceux qui utilisent PHPStorm et qui n'ont pas remarqué, quand vous avez essayé de faire appel à la méthode get() après la méthode getGet(), celle-ci ne vous est pas proposée par PHPStorm. Pour remédier à ce problème, changez la valeur de retour dans la classe Request de votre méthode getGet().

Hein ? J'ai rien compris 😞
<?php

namespace App\config;

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

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

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

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

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

Réessayez, ça devrait aller mieux maintenant. 

Mettez à jour votre Router avec cette syntaxe plus objet 😁

<?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()
    {
        $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($_POST);
                }
                else{
                    $this->errorController->errorNotFound();
                }
            }
            else{
                $this->frontController->home();
            }
        }
        catch (Exception $e)
        {
            $this->errorController->errorServer();
        }
    }
}

Essayez de naviguer dans votre application, ça doit toujours fonctionner 😉

Et pour $_POST ?  😅

En ce qui concerne cette variable superglobale, on va aller sur la page qui permet d'ajouter un d'article. Juste avant, pensez à désactiver la redirection faite dans le BackController par le header qu'on puisse voir le contenu de ce qui est soumis via $_POST.

Si vous avez supprimé le var_dump dans le Router, pensez à en remettre un qui afficher le contenu de la méthode getPost()

<?php
var_dump($this->request->getPost());

Vous remarquez qu'en ajoutant un nouvel article, le problème est le même que tout à l'heure, à vous de jouer pour le résoudre 😋

Vous avez dû remarquer qu'il y avait un peu plus de code à changer que précédemment, tout simplement parce que la soumission de l'article ne fonctionne plus correctement.

Allez, je vous donne les fichiers actualisés :

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 = $_SESSION;
    }

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

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

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

Router

<?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()
    {
        $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();
        }
    }
}

BackController

<?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);
            header('Location: ../public/index.php');
        }
        return $this->view->render('add_article', [
            'post' => $post
        ]);
    }
}

ArticleDAO

<?php

namespace App\src\DAO;

use App\config\Parameter;
use App\src\model\Article;

class ArticleDAO extends DAO
{
    private function buildObject($row)
    {
        $article = new Article();
        $article->setId($row['id']);
        $article->setTitle($row['title']);
        $article->setContent($row['content']);
        $article->setAuthor($row['author']);
        $article->setCreatedAt($row['createdAt']);
        return $article;
    }

    public function getArticles()
    {
        $sql = 'SELECT id, title, content, author, createdAt FROM article ORDER BY id DESC';
        $result = $this->createQuery($sql);
        $articles = [];
        foreach ($result as $row){
            $articleId = $row['id'];
            $articles[$articleId] = $this->buildObject($row);
        }
        $result->closeCursor();
        return $articles;
    }

    public function getArticle($articleId)
    {
        $sql = 'SELECT id, title, content, author, createdAt FROM article WHERE id = ?';
        $result = $this->createQuery($sql, [$articleId]);
        $article = $result->fetch();
        $result->closeCursor();
        return $this->buildObject($article);
    }

    public function addArticle(Parameter $post)
    {
        $sql = 'INSERT INTO article (title, content, author, createdAt) VALUES (?, ?, ?, NOW())';
        $this->createQuery($sql, [$post->get('title'), $post->get('content'), $post->get('author')]);
    }
}

Et voilà, réessayez de soumettre un article, ça fonctionne très bien 😊

Et pour $_SESSION ?

Vous vous rappelez du message d'erreur qu'on a laissé affiché ? On s'en occupe au prochain chapitre 😉

 

Bilan

Dans ce chapitre, nous avons mis en place une classe Request pour gérer la requête utilisateur au format objet.

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