MVC und PHP – Kurz und knackig erklärt
In letzter Zeit kommen immer häufiger Besucher auf meine Seite, die nach einer kurzen Beschreibung des MVC-Patterns in PHP suchen. Da dachte ich mir, ich versuche mich einfach mal an einer verständlichen und kurzen Beschreibung. Und da kommt sie auch schon!
Was bedeutet MVC?
Model View Controller. Das heißt auf deutsch dann etwa “Daten Anzeige Steuerung”. Das MVC-Prinzip oder MVC-Pattern ist wie auch das EVA-Prinzip ein Pattern, das sehr häufig angewandt wird, weil es die Wiederverwendbarkeit des Codes erheblich steigert. Natürlich nur, wenn man es richtig macht
Und um es richtig zu machen, muss man wissen, welche Schicht welche Aufgabe hat.
Model (Datenhaltungsschicht)
Das Model ist als einzige Schicht in der Anwendung in der Lage, Daten zu lesen und zu schreiben. Wo die Daten stehen, weiß nur das Model. Alle anderen Schichten müssen sich nicht um die Datenhaltung kümmern. Sie rufen nur Methoden auf, die ihnen die Daten liefern oder die die Daten speichern. Man implementiert dann also in der Regel gegen das Interface des Models.
View (Präsentationsschicht)
Der/Die View bekommt die Daten, die er anzeigen soll, vom Controller geliefert. View und Model haben niemals eine Verbindung miteinander. In der Webentwicklung gibt es beispielsweise HTML-Views, die eine normale Website ausgeben oder auch PDF-Views, die die Daten in Form einer PDF anzeigen.
Controller (Steuerungsschicht)
Die eigentliche Logik der Anwendung steckt im Controller. Er holt sich die Daten aus dem Model, verarbeitet sie und übergibt sie zur Ausgabe an den View. In der Regel weiß der Controller nicht, woher die Daten genau kommen und auch nicht, wie sie ausgegeben werden.
MVC in der Praxis
In der Praxis ist es leider nicht immer zu 100% möglich, die 3 Schichten komplett zu trennen. Beispielsweise kann es manchmal nötig sein, dass im Controller eine SQL-Query generiert wird, die dann vom Model verarbeitet wird. In diesem Fall weiß der Controller, dass die Daten aus einer Datenbank kommen. Man sollte aber immer versuchen, solche Situationen zu vermeiden, sofern die Performance dann nicht darunter leidet.
Außerdem werden sehr oft fertige Frameworks, wie z.B. mein Framework oder auch das ZEND Framework verwendet. Diese Frameworks bieten fertige Methoden und Klassen, um Websites schnell entwickeln zu können. Darunter befindet sich oftmals auch die Implementierung eines FrontControllers, der den Hauptteil des MVC-Patterns darstellt.
Der Vermittler im MVC: FrontController
Man kann sich vorstellen, dass es in einer Anwendung nicht nur einen Controller und ein Model gibt. Aber woher weiß die Anwendung, welcher Controller benötigt wird? Und wie wird dieser Controller geladen?
Die Antwort darauf ist ziemlich einfach. Es gibt eine “vierte Schicht” (die eigentlich keine wirkliche ist), die die Anfrage (Request) analysiert und so entscheidet, welcher Controller geladen werden muss. Diese vierte Schicht heißt FrontController.
Ein beispielhafter FC (FrontController) sieht so aus:
class FrontController
{
private $action;
private $controller;
public function __construct()
{
$this->action = isset($_GET["action"]) ? ucfirst(strtolower($_GET["action"])) : "index";
$this->action .= "_Action";
$this->controller = isset($_GET["controller"]) ? ucfirst(strtolower($_GET["controller"])) : "index";
}
public function run()
{
$controllerpath = "Controller/".$this->controller.".php";
if(file_exists($controllerpath))
{
require($controllerpath);
if(!class_exists($this->controller))
{
throw new Exception("Controller nicht gefunden! (1)");
}
$controller = new $this->controller;
if(in_array($this->action, get_class_methods($controller)))
{
$controller->{$this->action}();
}
else
{
throw new Exception("Action nicht gefunden");
}
}
else
{
throw new Exception("Controller nicht gefunden! (2)");
}
}
}
Es gibt dann z.B. Controller wie
class Index
{
public function Index_Action()
{
echo "Index::Index";
}
public function Test_Action()
{
echo "Index::Test";
}
}
oder
class Test
{
public function Index_Action()
{
echo "Test::Index";
}
public function Test_Action()
{
echo "Test::Test";
}
}
Die Index.php (wird sehr häufig Bootstrap-Datei genannt) ist sehr kurz und fängt nur Exceptions ab und instanziiert den FC:
error_reporting(E_ALL);
ini_set("display_errors", "on");
require("FrontController.php");
$frontcontroller = new FrontController;
try
{
$frontcontroller->run();
}
catch(Exception $e)
{
echo $e->getMessage();
}
In Wirklichkeit würde man die Exceptions wahrscheinlich anders behandeln, als sie einfach auszugeben.
Zu dieser Implementierung des FrontControllers ist noch zu sagen, dass keine Möglichkeit existiert, die Daten über verschiedene Views auszugeben. Aber dieses Tutorial sollte auch nur die Grundlagen zeigen. Wer mehr erfahren möchte, kann sich gerne mein MVC-Tutorial anschauen
- Request Router / Request Resolver meines Frameworks
- Syntaxhighlighter für Wordpress gefunden!
- Objektorientierte ID-Verwaltung in PHP
Dieser Artikel wurde von Simon verfasst.
Gelesen: 5946x heute: 5x
Dieser Artikel wurde am Freitag, Juli 24th, 2009 um 15:00 in den Kategorien OOP & Design Patterns geschrieben. Du kannst die Kommentare über den Feed (RSS 2.0) beobachten. Du kannst eine Antwort hinterlassen, oder einen Trackback von deiner Seite setzen.




Sehr guter Beitrag. Vielen Dank, gerade der Zusammenhang zwischen den einzelnen Controllern und dem FrontController ist mir hierdurch deutlich geworden. Nur zu meiner Verzeichnis-Struktur muss ich mir noch etwas überlegen.
Danke für dein Lob!
Hallo,
ich habe mal eine Frage und zwar zu diesem Satz:
“View und Model haben niemals eine Verbindung miteinander”
Das kann ich nicht so ganz nachvollziehen. Der Controller weißt doch das Model an Daten zu laden oder zu speichern oder was auch immer. Und er hat die Aufgabe die View bereit zu stellen. Wäre es da nicht sinnvoller die Daten aus dem Model direkt in der View anzuzeigen, anstatt noch den extra Weg über den Controller zu gehen und über diesen dann die Zuweisung der Daten an die View vorzunehmen.
Das würde auch dem Model entsprechen, dass die 3 Bestandteile “gleichberechtigt” vertreten sind und nicht das der Controller im Mittelpunkt steht.