Controller (C)
Die Aufgabe des Controllers ist die Ablaufsteuerung und die Ausführung der eigentlichen Programmlogiken. Er lädt notwendige Daten mit Hilfe des Models und stellt sie der View zur Verfügung. Auch Dinge wie Zugangskontrolle, Sessionverwaltung und Fehlerbehandlung finden hier statt.
Zunächst müssen wir anhand der vom Benutzer eingegebene URL den richtigen Controller und darin die richtige Methode (sogenannte Aktion) auswählen.
Wir gestalten unsere Links nach dem Schema
http://www.example.com/controller/action
.
Dabei ergänzen wir fehlende Teile durch „index“. Die URL der Startseite (www.example.com
) interpretieren wir also als www.example.com/index/index
. Damit ergibt sich als Controllerklasse IndexController
und als auszuführende Aktion die Methode indexAction
.
Natürlich dürfen wir unsere Klassen und Methoden nennen wie wir wollen, die Konvention ist allerdings beim Klassennamen ein „Controller“ und bei der Methode ein „Action“ anzuhängen.
Dieses sogenannte Routing erledigen wir in diesem einfachen Beispiel in der index.php
. Wir würzen noch etwas Errorhandling dazu und erhalten folgenden Programmcode.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// get the requested url $url = (isset($_GET['_url']) ? $_GET['_url'] : ''); $urlParts = explode('/', $url); // build the controller class $controllerName = (isset($urlParts[0]) && $urlParts[0] ? $urlParts[0] : 'index'); $controllerClassName = '\\Mvc\\Controller\\'.ucfirst($controllerName).'Controller'; // build the action method $actionName = (isset($urlParts[1]) && $urlParts[1] ? $urlParts[1] : 'index'); $actionMethodName = ucfirst($actionName).'Action'; try { if (!class_exists($controllerClassName)) { throw new \Mvc\Library\NotFoundException(); } $controller = new $controllerClassName(); if (!$controller instanceof \Mvc\Controller\Controller || !method_exists($controller, $actionMethodName)) { throw new \Mvc\Library\NotFoundException(); } $controller->$actionMethodName(); } catch (\Mvc\Library\NotFoundException $e) { http_response_code(404); echo 'Page not found: '.$controllerClassName.'::'.$actionMethodName; } catch (\Exception $e) { http_response_code(500); echo 'Exception: '.$e->getMessage().' '.$e->getTraceAsString(); } |
Der IndexController
unseres Beispiels sieht derweil noch unspektakulär aus.
1 2 3 4 5 6 7 8 9 |
namespace Mvc\Controller; class IndexController implements Controller { public function indexAction() { echo 'Hello World'; } } |
Wir packen gleich noch ein Interface dazu, das wir für instanceof
Prüfungen verwenden. In den meisten Anwendungen wird man noch eine abstrakte Basisklasse BaseController
einführen, von der alle Controller erben. Damit können dann allgemeine Aufgaben wie Sessionverwaltung erledigt werden.
Der vollständige Code bis hierher (v0.1).
Damit wir eine saubere Trennung von Business-Logik und Design erhalten, machen wir ab jetzt keine Ausgaben mehr im Controller. Diese Aufgabe übernimmt die View: Weiter mit der View