Commentaires
Il nous reste une dernière méthode à développer, l’exécution de la route trouvée.

Arthur, l'apprenti développeurAh je me disais aussi qu'il manquait encore quelque chose.

Tu va voir, ça va être rapide, il suffit d'ajouter une méthode Run dans la class Route. C'est méthode doit créer une nouvelle instance d'un controller, celui qui est précisé dans la route, et appeler l'action elle aussi précisé dans la route, en passant les paramètres, prévu dans notre httpRequest.

Arthur, l'apprenti développeurEffectivement c'est simple

{"language":"application/x-httpd-php","content":"<?php\n\tclass Route\n\t{\n\t\tprivate $_path;\n\t\tprivate $_controller;\n\t\tprivate $_action;\n\t\tprivate $_method;\n\t\tprivate $_param;\n\t\tprivate $_manager;\n\t\t\n\t\tpublic function __construct($route)\n\t\t{\n\t\t\t$this->_path = $route->path;\n\t\t\t$this->_controller = $route->controller;\n\t\t\t$this->_action = $route->action;\n\t\t\t$this->_method = $route->method;\n\t\t\t$this->_param = $route->param;\n\t\t\t$this->_manager = $route->manager;\n\t\t}\n\t\t\n\t\tpublic function getPath()\n\t\t{\n\t\t\treturn $this->_path;\n\t\t}\n\t\t\n\t\tpublic function getController()\n\t\t{\n\t\t\treturn $this->_controller;\n\t\t}\n\t\t\n\t\tpublic function getAction()\n\t\t{\n\t\t\treturn $this->_action;\n\t\t}\n\t\t\n\t\tpublic function getMethod()\n\t\t{\n\t\t\treturn $this->_method;\n\t\t}\n\t\t\n\t\tpublic function getParam()\n\t\t{\n\t\t\treturn $this->_param;\n\t\t}\n\t\t\n\t\tpublic function getManager()\n\t\t{\n\t\t\treturn $this->_manager;\n\t\t}\n\t\t\n\t\tpublic function run()\n\t\t{\n\t\t\t$controller = new $this->_controller();\n\t\t\t$controller->$this->_action();\n\t\t}\n\t}","filename":"Route.php"}


Arthur, l'apprenti développeurPas si facile en fait, je bloque sur le passage des paramètres vu que je n'ai pas httpRequest dans la class Route mais le contraire, la route dans HttpRequest. Il y a un moyen de remonter au parent?

Non il n'y a aucun moyen, il faut faire comme d'habitude, passer en paramètre. Et il faudra penser à ajouter un accesseur vers param dans HttpRequest.

Arthur, l'apprenti développeurJe le fais tout de suite !

{"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()\n\t\t{\n\t\t\t$this->_url = $_SERVER['REQUEST_URI'];\n\t\t\t$this->_method = $_SERVER['REQUEST_METHOD'];\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\t$this->_param[] = $param;\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\t$this->_param[] = $param;\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic function getRoute()\n\t\t{\n\t\t\treturn $this->_route;\t\n\t\t}\n\t\t\n\t\tpublic function getParam()\n\t\t{\n\t\t\treturn $this->_param;\t\n\t\t}\n\t}","filename":"HttpRequest.php"}


Par contre tu va avoir un problème sur cette ligne :

{"language":"application/x-httpd-php","content":"<?php\n\t$controller->$this->_action();","filename":"exemple"}


La navigation dans les propriété et méthode d'une classe se fait étape par étape, donc là l'instruction va essayer de récupérer comme propriété la valeur de $this, puis seulement ensuite essayer d'accéder à l'action de cette propriété qui n'aura pas été trouvée. Il faut indiquer à cette ligne que tu veux executer l'action $this->_action de ce contrôleur, pour cela tu peux entourer l'expression accolades, elle sera alors traité comme un bloc avant d'être utiliser par le contrôleur.

Arthur, l'apprenti développeurComme ça?

{"language":"application/x-httpd-php","content":"<?php\n\tclass Route\n\t{\n\t\tprivate $_path;\n\t\tprivate $_controller;\n\t\tprivate $_action;\n\t\tprivate $_method;\n\t\tprivate $_param;\n\t\tprivate $_manager;\n\t\t\n\t\tpublic function __construct($route)\n\t\t{\n\t\t\t$this->_path = $route->path;\n\t\t\t$this->_controller = $route->controller;\n\t\t\t$this->_action = $route->action;\n\t\t\t$this->_method = $route->method;\n\t\t\t$this->_param = $route->param;\n\t\t\t$this->_manager = $route->manager;\n\t\t}\n\t\t\n\t\tpublic function getPath()\n\t\t{\n\t\t\treturn $this->_path;\n\t\t}\n\t\t\n\t\tpublic function getController()\n\t\t{\n\t\t\treturn $this->_controller;\n\t\t}\n\t\t\n\t\tpublic function getAction()\n\t\t{\n\t\t\treturn $this->_action;\n\t\t}\n\t\t\n\t\tpublic function getMethod()\n\t\t{\n\t\t\treturn $this->_method;\n\t\t}\n\t\t\n\t\tpublic function getParam()\n\t\t{\n\t\t\treturn $this->_param;\n\t\t}\n\t\t\n\t\tpublic function getManager()\n\t\t{\n\t\t\treturn $this->_manager;\n\t\t}\n\t\t\n\t\tpublic function run($httpRequest)\n\t\t{\n\t\t\t$controller = new $this->_controller();\n\t\t\t$controller->{$this->_action}($httpRequest->getParam());\n\t\t}\n\t}","filename":"Route.php"}


Oui c'est bien ça. Deux derniers détail sur cette méthode run, tout d'abord il faudrait penser à vérifier si le contrôleur existe et sinon il faut gérer l'erreur, la fonction class_exists te seras très utile. Ensuite il faut aussi vérifier que la méthode $this->_action existe bien dans le contrôleur avant de l'appeler, et de même gérer l'éventuelle erreur. Tu peux utiliser la fonction method_exists pour ça.
Et enfin, en procédant de cette façon, tes actions vont recevoir un seul et unique paramètre qui est un tableau qui contiens les paramètres, ça ne sera pas très pratique à utiliser. Il serait bien plus pratique d'avoir une variable paramètre dans l'action pour chaque paramètre qui est prévu.

Arthur, l'apprenti développeurMais comment je fais, je ne sais pas combien il va y avoir de paramètre à l'avance, il faut que je fasse un switch pour compter les paramètre, et ensuite faire plein d'action pour un, deux, trois ou plus de paramètre comme ça?

{"language":"application/x-httpd-php","content":"<?php\n\tswitch(count($param))\n\t{\n\t\tcase 1:\n\t\t\t$controleur->$action($param[0]);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t$controleur->$action($param[0],$param[1]);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t$controleur->$action($param[0],$param[1],$param[2]);\n\t\t\tbreak;\n\t\t[...]\n\t}","filename":"exemple"}


Hola non, ce serait contre productif et pas générique du tout, si tu te limite à cinq le jour où tu crée une action avec six paramètre tu devras mettre à jour ce switch pour six, puis le jour où tu crée une action avec sept paramètres... Bref non il y a beaucoup plus simple avec l'opérateur de décomposition.

Arthur, l'apprenti développeurLe quoi?

L'opérateur de décomposition. c'est un opérateur qui permet de décomposer un tableau en plusieurs variable pour les passer en paramètres d'une fonction.

Arthur, l'apprenti développeurDonc je dois juste ajouter ... devant mes paramètres?

Oui c'est ça. Et n'oublie pas aussi, si dans ta route tu souhaite appeler le contrôleur User, il faut en fait appeler le fichier et la classe UserController, donc il faudra penser à concaténer Controller après. Et aussi, le BaseController attend deux paramètres dans son constructeur qui sont httpRequest et config.



{"language":"application/x-httpd-php","content":"<?php\n\tclass Route\n\t{\n\t\tprivate $_path;\n\t\tprivate $_controller;\n\t\tprivate $_action;\n\t\tprivate $_method;\n\t\tprivate $_param;\n\t\tprivate $_manager;\n\t\t\n\t\tpublic function __construct($route)\n\t\t{\n\t\t\t$this->_path = $route->path;\n\t\t\t$this->_controller = $route->controller;\n\t\t\t$this->_action = $route->action;\n\t\t\t$this->_method = $route->method;\n\t\t\t$this->_param = $route->param;\n\t\t\t$this->_manager = $route->manager;\n\t\t}\n\t\t\n\t\tpublic function getPath()\n\t\t{\n\t\t\treturn $this->_path;\n\t\t}\n\t\t\n\t\tpublic function getController()\n\t\t{\n\t\t\treturn $this->_controller;\n\t\t}\n\t\t\n\t\tpublic function getAction()\n\t\t{\n\t\t\treturn $this->_action;\n\t\t}\n\t\t\n\t\tpublic function getMethod()\n\t\t{\n\t\t\treturn $this->_method;\n\t\t}\n\t\t\n\t\tpublic function getParam()\n\t\t{\n\t\t\treturn $this->_param;\n\t\t}\n\t\t\n\t\tpublic function getManager()\n\t\t{\n\t\t\treturn $this->_manager;\n\t\t}\n\t\t\n\t\tpublic function run($httpRequest,$config)\n\t\t{\n\t\t\t$controller = null;\n\t\t\t$controllerName = $this->_controller . \"Controller\";\n if(class_exists($controllerName))\n {\n\t\t\t\t\n $controller = new $controllerName($httpRequest,$config);\n if(method_exists($controller, $this->_action))\n {\n $controller->{$this->_action}(...$httpRequest->getParam());\n }\n else\n {\n throw new ActionNotFoundException();\n }\n }\n else\n {\n throw new ControllerNotFoundException();\n }\n\t\t\t\n\t\t}\n\t}","filename":"Route.php"}



On y est ! il ne reste plus qu'à appeler la méthode run de la route.

Arthur, l'apprenti développeurDans l'index j'imagine?

Oui c'est bien ça.

{"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->getRoute()->run();\n\t}\n\tcatch(Exception $e)\n\t{\n echo \"Une erreur s'est produite\";\n\t}","filename":"index.php"}


Tu va avoir un problème, la méthode getRoute() n'existe pas dans httpRequest. On pourrais la créer mais il faut aussi penser à passer en paramètre httpRequest et config à la méthode run. Je te propose que l'on fasse de nouveau une méthode passe plat dans httpRequest avec en paramètre $config, qui appelera run de la route en lui passant $this et $config en paramètre.

Arthur, l'apprenti développeurOn peut lui passer $this en paramètre? mais ça correspondra à quoi?

Et bien on sera dans une méthode de la classe httpRequest, donc $this représentera l'objet httpRequest qui a appelé cette méthode. Et c'est bien l'objet que l'on souhaite passer à run.

Arthur, l'apprenti développeurOh d'accord je fait ça.

{"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()\n\t\t{\n\t\t\t$this->_url = $_SERVER['REQUEST_URI'];\n\t\t\t$this->_method = $_SERVER['REQUEST_METHOD'];\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\t$this->_param[] = $param;\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\t$this->_param[] = $param;\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic function getRoute()\n {\n return $this->_route;\n }\n\t\t\n\t\tpublic function getParam()\n\t\t{\n\t\t\treturn $this->_param;\t\n }\n\t\t\n\t\tpublic function run($config)\n {\n $this->_route->run($this,$config);\n }\n\t}","filename":"HttpRequest.php"}



Arthur, l'apprenti développeurEt je modifie l'index en même temps.

{"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 echo \"Une erreur s'est produite\";\n\t}","filename":"index.php"}


Maintenant ouvre ton navigateur à l'url du projet http://localhost/{dossier projet}/

Arthur, l'apprenti développeurJ'ai une erreur...



Et elle n'est pas très précise. On va compléter ça pour avoir plus de détail. J'ai terminé cette partie
Demander de l'assistance