J'ai beaucoup lu sur comment et pourquoi utiliser une approche MVC dans une application. J'ai vu et compris des exemples de modèle, j'ai vu et compris des exemples de View ... mais je suis TOUJOURS un peu confus sur le contrôleur. J'aimerais vraiment voir un exemple suffisamment complet de contrôleurs. (dans PHP si possible, mais tout langage pourra vous aider)
Je vous remercie.
PS: Ce serait également bien si je pouvais voir un exemple de page index.php, qui décide quel contrôleur utiliser et comment.
MODIFIER: Je sais ce que le contrôleur est travail, je ne comprends pas vraiment comment accomplir cela en POO.
Exemple de demande
Mettez quelque chose comme ceci dans votre index.php
:
<?php
// Holds data like $baseUrl etc.
include 'config.php';
$requestUrl = 'http://'.$_SERVER['HTTP_Host'].$_SERVER['REQUEST_URI'];
$requestString = substr($requestUrl, strlen($baseUrl));
$urlParams = explode('/', $requestString);
// TODO: Consider security (see comments)
$controllerName = ucfirst(array_shift($urlParams)).'Controller';
$actionName = strtolower(array_shift($urlParams)).'Action';
// Here you should probably gather the rest as params
// Call the action
$controller = new $controllerName;
$controller->$actionName();
Vraiment basique, mais vous avez l’idée… (Je ne me suis pas non plus occupé du chargement de la classe de contrôleur, mais je suppose que cela peut être fait soit par chargement automatique, soit vous savez comment le faire.)
Exemple de contrôleur simple (controllers/login.php):
<?php
class LoginController
{
function loginAction()
{
$username = $this->request->get('username');
$password = $this->request->get('password');
$this->loadModel('users');
if ($this->users->validate($username, $password))
{
$userData = $this->users->fetch($username);
AuthStorage::save($username, $userData);
$this->redirect('secret_area');
}
else
{
$this->view->message = 'Invalid login';
$this->view->render('error');
}
}
function logoutAction()
{
if (AuthStorage::logged())
{
AuthStorage::remove();
$this->redirect('index');
}
else
{
$this->view->message = 'You are not logged in.';
$this->view->render('error');
}
}
}
Comme vous le voyez, le contrôleur prend en charge le "flux" de l'application - la logique dite d'application. Il ne prend pas en charge le stockage et la présentation des données. Il rassemble plutôt toutes les données nécessaires (en fonction de la demande en cours) et les assigne à la vue ...
Notez que cela ne fonctionnerait avec aucun framework que je connaisse, mais je suis sûr que vous savez ce que les fonctions sont censées faire.
Imaginez-vous des écrans dans une interface utilisateur, un écran dans lequel un utilisateur entre certains critères de recherche, un écran dans lequel une liste de résumés des enregistrements correspondants est affichée et un écran dans lequel, lorsqu'un enregistrement est sélectionné, il est affiché pour édition. Il y aura une certaine logique relative à la recherche initiale sur les lignes de
if search criteria are matched by no records
redisplay criteria screen, with message saying "none found"
else if search criteria are matched by exactly one record
display edit screen with chosen record
else (we have lots of records)
display list screen with matching records
Où doit aller cette logique? Pas dans la vue ou le modèle sûrement? C'est donc le travail du contrôleur. Le responsable du traitement serait également chargé de prendre les critères et d’appeler la méthode Model pour la recherche.
<?php
class App {
protected static $router;
public static function getRouter() {
return self::$router;
}
public static function run($uri) {
self::$router = new Router($uri);
//get controller class
$controller_class = ucfirst(self::$router->getController()) . 'Controller';
//get method
$controller_method = strtolower((self::$router->getMethodPrefix() != "" ? self::$router->getMethodPrefix() . '_' : '') . self::$router->getAction());
if(method_exists($controller_class, $controller_method)){
$controller_obj = new $controller_class();
$view_path = $controller_obj->$controller_method();
$view_obj = new View($controller_obj->getData(), $view_path);
$content = $view_obj->render();
}else{
throw new Exception("Called method does not exists!");
}
//layout
$route_path = self::getRouter()->getRoute();
$layout = ROOT . '/views/layout/' . $route_path . '.phtml';
$layout_view_obj = new View(compact('content'), $layout);
echo $layout_view_obj->render();
}
public static function redirect($uri){
print("<script>window.location.href='{$uri}'</script>");
exit();
}
}
<?php
class Router {
protected $uri;
protected $controller;
protected $action;
protected $params;
protected $route;
protected $method_prefix;
/**
*
* @return mixed
*/
function getUri() {
return $this->uri;
}
/**
*
* @return mixed
*/
function getController() {
return $this->controller;
}
/**
*
* @return mixed
*/
function getAction() {
return $this->action;
}
/**
*
* @return mixed
*/
function getParams() {
return $this->params;
}
function getRoute() {
return $this->route;
}
function getMethodPrefix() {
return $this->method_prefix;
}
public function __construct($uri) {
$this->uri = urldecode(trim($uri, "/"));
//defaults
$routes = Config::get("routes");
$this->route = Config::get("default_route");
$this->controller = Config::get("default_controller");
$this->action = Config::get("default_action");
$this->method_prefix= isset($routes[$this->route]) ? $routes[$this->route] : '';
//get uri params
$uri_parts = explode("?", $this->uri);
$path = $uri_parts[0];
$path_parts = explode("/", $path);
if(count($path_parts)){
//get route
if(in_array(strtolower(current($path_parts)), array_keys($routes))){
$this->route = strtolower(current($path_parts));
$this->method_prefix = isset($routes[$this->route]) ? $routes[$this->route] : '';
array_shift($path_parts);
}
//get controller
if(current($path_parts)){
$this->controller = strtolower(current($path_parts));
array_shift($path_parts);
}
//get action
if(current($path_parts)){
$this->action = strtolower(current($path_parts));
array_shift($path_parts);
}
//reset is for parameters
//$this->params = $path_parts;
//processing params from url to array
$aParams = array();
if(current($path_parts)){
for($i=0; $i<count($path_parts); $i++){
$aParams[$path_parts[$i]] = isset($path_parts[$i+1]) ? $path_parts[$i+1] : null;
$i++;
}
}
$this->params = (object)$aParams;
}
}
}