{"language":"application/x-httpd-php","content":"<?php\n\techo \"Une erreur s'est produite\";","filename":"exemple"}
On va modifier ça pour avoir plus d'informations sur les erreurs. Tu va créer un contrôleur Error, avec une méthode Show, celle ci prendra un paramètre exception, l'ajoutera aux paramètres de la vue et appellera la vue error.
Oula, ça fait beaucoup de chose tout ça.
Pas vraiment, essaye de le faire tu va voir.
{"language":"application/x-httpd-php","content":"<?php\n\tclass ErrorController\n\t{\n\t\tpublic function Show($exception)\n\t\t{\n\t\t\t$this->addParam(\"exception\",$exception);\n\t\t\t$this->view(\"error\");\n\t\t}\n\t}","filename":"ErrorController.php"}
C'est ça?
Oui c'est bien ça. Maintenant tu va ajouter une vue error.php dans un nouveau dossier error dans les vues. Et dans cette vu tu va afficher trois élément:
- Un titre avec une chaîne de caractère comme "Une erreur s'est produite".
- Un bloc de texte avec le message de l'exception, tu peux la récupérer en utilisant la méthode getMessage de la variable exception.
- Un deuxième bloc de texte avec la pile d’exécution de l'exception, celle ci tu la récupère avec la méthode getTraceAsString
{"language":"application/x-httpd-php","content":"<div class=\"error\">\n\t<h1>Une erreur s'est produite</h1>\n\t<div class=\"error-message\">Message : <?= $exception->getMessage(); ?></div>\n\t<div class=\"error-stack\">Pile d'execution : <?= $exception->getTraceAsString(); ?></div>\n</div>","filename":"error.php"}
Il faut maintenant ajouter la route dans notre fichier de route, pour qu'il puisse trouver le contrôleur.
{"language":"application/json","content":"[{\n\t\"path\" : \"/\",\n\t\"controller\" : \"Home\",\n\t\"action\" : \"Home\",\n\t\"method\" : \"GET\",\n\t\"param\" : [],\n\t\"manager\": []\n},\n{\n\t\"path\" : \"/Login\",\n\t\"controller\" : \"Home\",\n\t\"action\" : \"Login\",\n\t\"method\" : \"GET\",\n\t\"param\" : [],\n\t\"manager\": []\n},\n{\n\t\"path\" : \"/Login\",\n\t\"controller\" : \"Home\",\n\t\"action\" : \"Authenticate\",\n\t\"method\" : \"POST\",\n\t\"param\" : [\n\t\t\"login\",\n\t\t\"password\"\n\t],\n\t\"manager\": [\n\t\t\"User\"\n\t]\n},\n{\n\t\"path\" : \"/Error\",\n\t\"controller\" : \"Error\",\n\t\"action\" : \"Show\",\n\t\"method\" : \"GET\",\n\t\"param\" : [],\n\t\"manager\": []\n}]","filename":"route.json"}
Et dans l'index, au lieu du echo, tu va tout simplement appeler de nouveau le routeur, mais au lieu de lui passer un httpRequest construit avec la requête, tu va le construire avec l'url "/Error". Il va falloir modifier un peu le constructeur de HttpRequest pour qu'il puisse prendre deux paramètre facultatif qui sont l'url et la méthode. Tu peux utiliser des paramètres facultatif dans le constructeur en les définissant à null. Et ensuite dans le constructeur je te propose d'utiliser une condition ternaire, pour vérifier si le paramètre est à null tu utilise la variable $_SERVER, sinon tu prend le paramètre.
Paramètre facultatif ok, par contre condition ternaire, ça ne me dit rien du tout...
Ah c'est comme un if, mais sur une seule ligne et ça ressemble à ça :
{"language":"application/x-httpd-php","content":"<?php\n\t(condition)? true : false;","filename":"exemple"}
Si on en reviens à ce que je disais avant, ça donnerait :
{"language":"application/x-httpd-php","content":"<?php\n\tfunction Exemple($variable = null)\n\t{\n\t\t$this->propriete = (is_null($variable))? $_SERVEUR[\"champ\"] : $variable;\t\n\t}","filename":"exemple"}
Autrement dit, la propriété de la classe prendra la valeur de $variable si on a passé un paramètre, et sinon la valeur de $_SERVEUR["champ"]
J'ai compris !
{"language":"application/x-httpd-php","content":"<?php\n\tclass HttpRequest\n\t{\n\t\tprivate $_url;\n\t\tprivate $_method;\n\t\tprivate $_param;\n\t\tprivate $_route;\n\t\t\n\t\tpublic function __construct($url = null, $method = null)\n\t\t{\n\t\t\t$this->_url = (is_null($url))?$_SERVER['REQUEST_URI']:$url;\n\t\t\t$this->_method = (is_null($method))?$_SERVER['REQUEST_METHOD']:$method;\n\t\t\t$this->_param = array();\n\t\t}\n\t\t\n\t\tpublic function getUrl()\n\t\t{\n\t\t\treturn $this->_url;\t\n\t\t}\n\t\t\n\t\tpublic function getMethod()\n\t\t{\n\t\t\treturn $this->_method;\t\n\t\t}\n\t\t\n\t\tpublic function getParams()\n\t\t{\n\t\t\treturn $this->_params;\t\n\t\t}\n\t\t\n\t\tpublic function setRoute($route)\n\t\t{\n\t\t\t$this->_route = $route;\t\n\t\t}\n\t\t\n\t\tpublic function bindParam()\n\t\t{\n\t\t\tswitch($this->_method)\n\t\t\t{\n\t\t\t\tcase \"GET\":\n\t\t\t\tcase \"DELETE\":\n\t\t\t\t\tforeach($this->_route->getParam() as $param)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(isset($_GET[$param]))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_param[] = $_GET[$param];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tcase \"POST\":\n\t\t\t\tcase \"PUT\":\n\t\t\t\t\tforeach($this->_route->getParam() as $param)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(isset($_POST[$param]))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_param[] = $_POST[$param];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n }\n \n\t\tpublic function getRoute()\n {\n return $this->_route;\n }\n\t\t\n public function getParam()\n\t\t{\n\t\t\treturn $this->_param;\t\n }\n \n\t\tpublic function run($config)\n {\n $this->_route->run($this,$config);\n }\n\t}","filename":"HttpRequest.php"}
Parfait, et maintenant l'index.
{"language":"application/x-httpd-php","content":"<?php\n\t$configFile = file_get_contents(\"Config/config.json\");\n\t$config = json_decode($configFile);\n\n\tspl_autoload_register(function($class) use($config)\n\t{\n\t\tforeach($config->autoloadFolder as $folder)\n\t\t{\n\t\t\tif(file_exists($folder . '/' . $class . '.php'))\n\t\t\t{\n\t\t\t\trequire_once($folder . '/' . $class . '.php');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t});\n\ttry\n\t{\n\t\t$httpRequest = new HttpRequest();\n $router = new Router();\n $httpRequest->setRoute($router->findRoute($httpRequest));\n $httpRequest->run($config);\n\t}\n\tcatch(Exception $e)\n\t{\n $httpRequest = new HttpRequest(\"/Error\",\"GET\");\n $router = new Router();\n $httpRequest->setRoute($router->findRoute($httpRequest));\n $httpRequest->run($config);\n\t}","filename":"index.php"}
Et il faut pouvoir ajouter l'exception en paramètre de httpRequest, on va éviter de le passer dans la route, car elle ne sera pas présente dans les variables $_GET et $_POST. Il nous faut donc un moyen supplémentaire d'ajouter un paramètre dans httpRequest.
Une méthode addParam?
Tout à fait.
{"language":"application/x-httpd-php","content":"<?php\n\tclass HttpRequest\n\t{\n\t\tprivate $_url;\n\t\tprivate $_method;\n\t\tprivate $_param;\n\t\tprivate $_route;\n\t\t\n\t\tpublic function __construct($url = null, $method = null)\n\t\t{\n\t\t\t$this->_url = (is_null($url))?$_SERVER['REQUEST_URI']:$url;\n\t\t\t$this->_method = (is_null($method))?$_SERVER['REQUEST_METHOD']:$method;\n\t\t\t$this->_param = array();\n\t\t}\n\t\t\n\t\tpublic function getUrl()\n\t\t{\n\t\t\treturn $this->_url;\t\n\t\t}\n\t\t\n\t\tpublic function getMethod()\n\t\t{\n\t\t\treturn $this->_method;\t\n\t\t}\n\t\t\n\t\tpublic function getParams()\n\t\t{\n\t\t\treturn $this->_params;\t\n\t\t}\n\t\t\n\t\tpublic function setRoute($route)\n\t\t{\n\t\t\t$this->_route = $route;\t\n\t\t}\n\t\t\n\t\tpublic function bindParam()\n\t\t{\n\t\t\tswitch($this->_method)\n\t\t\t{\n\t\t\t\tcase \"GET\":\n\t\t\t\tcase \"DELETE\":\n\t\t\t\t\tforeach($this->_route->getParam() as $param)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(isset($_GET[$param]))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_param[] = $_GET[$param];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tcase \"POST\":\n\t\t\t\tcase \"PUT\":\n\t\t\t\t\tforeach($this->_route->getParam() as $param)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(isset($_POST[$param]))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_param[] = $_POST[$param];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n }\n\t\t\n public function getRoute()\n {\n return $this->_route;\n }\n\t\t\n public function getParam()\n\t\t{\n\t\t\treturn $this->_param;\t\n }\n \n\t\tpublic function run($config)\n {\n $this->_route->run($this,$config);\n }\n\n public function addParam($value)\n {\n $this->_param[] = $value;\n }\n\t}","filename":"HttpRequest.php"}
Et reste à ajouter le paramètre avant le run dans l'index.
{"language":"application/x-httpd-php","content":"<?php\n\t$configFile = file_get_contents(\"Config/config.json\");\n\t$config = json_decode($configFile);\n\n\tspl_autoload_register(function($class) use($config)\n\t{\n\t\tforeach($config->autoloadFolder as $folder)\n\t\t{\n\t\t\tif(file_exists($folder . '/' . $class . '.php'))\n\t\t\t{\n\t\t\t\trequire_once($folder . '/' . $class . '.php');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t});\n\ttry\n\t{\n\t\t$httpRequest = new HttpRequest();\n $router = new Router();\n $httpRequest->setRoute($router->findRoute($httpRequest));\n $httpRequest->run($config);\n\t}\n\tcatch(Exception $e)\n\t{\n $httpRequest = new HttpRequest(\"/Error\",\"GET\");\n $router = new Router();\n $httpRequest->setRoute($router->findRoute($httpRequest));\n\t\t$httpRequest->addParam(,$e);\n $httpRequest->run($config);\n\t}","filename":"index.php"}
J'ai toujours une erreur...
Oui mais cette fois ci elle a été traitée par le contrôleur d'erreur et on a un peu plus de détail. Si tu te souviens, dans l'exception PropertyNotFoundException on avait ajouter des paramètres ainsi qu'une méthode getMoreDetail.
Oui !
On va faire pareil sur NoRouteFoundException, on va ajouter un paramètre httpRequest, et une méthode getMoreDetail qui affiche un message avec l'url et la méthode de la requête.
Je m'en occupe
{"language":"application/x-httpd-php","content":"<?php\n\tclass NoRouteFoundException extends Exception\n\t{\n\t\tprivate $_httpRequest;\n\t\t\n\t\tpublic function __construct($httpRequest,$message = \"No route has been found\")\n\t\t{\n\t\t\t$this->_httpRequest = $httpRequest;\n\t\t\tparent::__construct($message, \"0002\");\n\t\t}\n\t\t\n\t\tpublic function getMoreDetail()\n\t\t{\n\t\t\treturn \"Route '\" . $this->_httpRequest->getUrl() . \"' has not been found with method '\" . $this->_httpRequest->getMethod() . \"'\";\n\t\t}\n\t}","filename":"NoRouteFoundException.php"}
Et dans le routeur, on va ajouter la variable $httpRequest à la levée de l'exception.
{"language":"application/x-httpd-php","content":"<?php\n\tclass Router\n\t{\n\t\tprivate $_listRoute;\n\t\t\n\t\tpublic function __construct()\n\t\t{\n\t\t\t$stringRoute = file_get_contents('Config/route.json');\n\t\t\t$this->_listRoute = json_decode($stringRoute);\n\t\t}\n\t\t\n\t\tpublic function findRoute($httpRequest)\n\t\t{\n\t\t\t$routeFound = array_filter($this->_listRoute,function($route) use ($httpRequest){\n\t\t\t\treturn preg_match(\"#^\" . $route->path . \"$#\", $httpRequest->getUrl()) && $route->method == $httpRequest->getMethod();\n\t\t\t});\n\t\t\t$numberRoute = count($routeFound);\n\t\t\tif($numberRoute > 1)\n\t\t\t{\n\t\t\t\tthrow new MultipleRouteFoundException();\n\t\t\t}\n\t\t\telse if($numberRoute == 0)\n\t\t\t{\n\t\t\t\tthrow new NoRouteFoundException($httpRequest);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn new Route(array_shift($routeFound));\t\n\t\t\t}\n\t\t}\n\t}","filename":"Router.php"}
Enfin on va ajouter dans la vue error une condition, si la méthode getMoreDetail de l'exception existe, on va l'appeler pour l'afficher dans un nouveau div. Normalement tu connais déjà tout ce qu'il faut pour réaliser ça.
Oui je vais réutiliser method_exists
{"language":"application/x-httpd-php","content":"<div class=\"error\">\n\t<h1>Une erreur s'est produite</h1>\n\t<div class=\"error-message\">Message : <?= $exception->getMessage(); ?></div>\n\t<div class=\"error-stack\">Pile d'execution : <?= $exception->getTraceAsString(); ?></div>\n <?php if(method_exists($exception,\"getMoreDetail\")){ ?>\n <div class=\"error-detail\"><?= $exception->getMoreDetail(); ?></div>\n <?php } ?>\n</div>","filename":"error.php"}
Maintenant recharge ta page
J'ai toujours une erreur mais c'est bizarre il essaie de trouver la route de mon dossier de projet en fait...
Et oui, la variable $_SERVER["REQUEST_URI"] retourne tout ce qui est dans l'url après le nom de domaine, ici on travaille en local, le nom de domaine est localhost, donc pour lui la route est /mvc-php/ le nom de mon dossier de projet. J'ai terminé cette partie