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
Tolles Tutorial !!
Eine Frage habe ich jedoch dazu:
$stmt->execute($options[‚bind‘]);
welche Parameter stehen in $options ?
LG
Der $options Parameter bei den find Funktionen, soll möglichst flexibel einsetzbar sein.
Bisher versteht die findFirst() zum einen direkt eine ID ModelBase(23) und zum anderen die Definition von Parametern. Dann muss ein Array übergeben werden, dass sowohl die WHERE Bedingung und Platzhalterdefinition als auch die Werte für die Platzhalter enthält. Das sieht dann so aus:
[
'criteria' => 'userId = :uid',
'bind' => [':uid'=>5],
]
Hier gilt die Syntax von PDO.
Die find() Funktion versteht nur die zweite Variante, da ja explizit mehrere Ergebnisse gefunden werden sollen und die ID immer nur eines liefern würde.
Hallo,
geniales Tutorial (vielen Dank!), welches ich gerne dazu nutzen möchte, meine Kenntnisse in OOP zu vertiefen!
Eine Frage:
Unterstützt dieser MVC-Ansatz auch das Konzept Post-Redirect-Get? Ich möchte, dass der Benutzer die Vor-/Zurück-Buttons im Browser nutzen kann, OHNE dass er ein Post-Formular extra noch einmal re-loaden muss.
Danke und viele Grüße
Jörg
Hallo Jörg,
das funktioniert ohne Probleme.
Was du nach einen POST-Request an den User zurück gibst (Webseite, Redirect, …) hat mit MVC an sich nichts zu tun.
Und jede Action hört erst mal auf alle Anfragen egal welcher Typ (GET, POST, PUT, …). Weitere Einschränkungen wären in diesem einfachen Beispiel die Aufgabe des Entwicklers. Praktisch alle Frameworks bieten hier Unterstützung an.
Hoffe das hilft!