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.

mvcModel (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 🙂

1 Star2 Stars3 Stars4 Stars5 Stars (15 Stimme, durchschnittlich 3,07 / 5)
Loading...


20 Kommentare zu “MVC und PHP – Kurz und knackig erklärt”

  1. 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.

  2. Danke für dein Lob!

  3. 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.

  4. Nein, ich sehe das anders.

    Meiner Meinung nach muss der Controller die Macht haben und nicht alle Teile gleich viel. Der Controller holt die Daten aus dem Model, verarbeitet sie ggf. und schickt sie dann zur Ausgabe an die View.

    View und Model haben niemals eine Verbindung! Das entspricht meinem Verständnis von MVC.

    MfG
    Simon

  5. Das ist interessant mit dem Frontcontroller und macht Sinn!

    In dieser Art Sichtweise, wo das View keine Verbindung zum Modell hat, kann die Modell Klasse im Grunde nur aus statischen Methoden bestehen. Diese Art der Implementierung wo die Daten im View gespeichert werden und der Controller die Daten vom Modell besorgt, finde ich recht interessant.

    Nach klassischem MVC Muster weiß aber schon das View über sein Modell. Wenn sich die Daten im Modell ändern wird das zugehörige View informiert und darauf kann das View die geänderten Daten abrufen.
    Die persistenten Daten befinden sich also im Modell und nicht im View.
    .-= devarni´s last blog ..Benchmark- VirtualBox vs VMware- Part2 2010 =-.

  6. Model und statische Methoden? Du hast da was falsch verstanden 😉 Warum sollte das so sein?

    Du musst wissen, dass MVC in PHP grundlegend anders ist als in anderen Sprachen, wie z.b. C++. Denn die PHP-Skripts sind sehr kurzlebig und an das HTTP gebunden.

  7. gute beschreibung!

    danke

  8. „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.“

    Solange solche Aussagen veröffentlicht werden, kann es nicht wirklich einen Fortschritt in der Verbesserung der Qualität von PHP-Entwicklern geben. Wenn man nicht gerade ein primitives Gästebuch entwickelt, dann ist diese Aussage kriminell.

    Ebenso wie viele nicht wissen, dass SRP, SoC oder OCP elementare Prinzipien von OOP sind, werden solche völlig falschen Behauptungen aufgestellt, die dann leider noch unbegabte Entwickler glauben – und noch schlimmer anwenden.

    Die Prinzipien der OOP gelten für die Architektur ebenso: entweder du machst eine saubere Kapselung, hast streng definierte Verantwortungen und saubere Schnittstellen. Oder du kommst in Teufels Küche.

    MVC sollte übrigens nur im Teil „M“ Businesslogik Komplexität enthalten, V und C sind rein nur für die Ein- und Ausgabe zuständig und dumm. Zend z.B. macht es richtig. Fast alle anderen sind Scharlatane oder wollen, dass man mit ihren Frameworks nur Gästebücher entwickelt.

  9. Zitat Zampano: „MVC sollte übrigens nur im Teil “M” Businesslogik Komplexität enthalten, V und C sind rein nur für die Ein- und Ausgabe zuständig und dumm.“

    Dazu gibts unterschiedliche Meinungen; man kann ebenso das Model „dumm“ halten und einen komplexen Controller implementieren. Alles Geschmacks- / Ansichtssache – vor allem im Bereich der Webentwicklung – und kein Grund, Gift zu spucken.

    Die Idee, im Controller (ausnahmsweise) einen DB-Query zu generieren, ist allerdings absurd.

    cx

  10. Ich bin auch der Meinung, dass der Controller der schlaue Teil sein soll und das Model nur für die Datenspeicherung zuständig ist.

    Erklär uns doch mal, warum das NICHT der Fall ist!

  11. Huhu,

    auch wenn ich etwas spät an die Diskussion stoße, aber beim Thema MVC-Gliederung gibt tatsächlich oft Diskussionsbedarf, da nirgendwo fest definiert ist, was wo hingehört. Natürlich ist klar, dass die Daten aus dem Model kommen und diese vom Controller an die View gesendet werden.

    Dass eine View direkten Kontakt zum Model hat ist meiner Meinung nach Unsinn, gebe somit Simon Recht. Ansonsten ist der Controller nutzlos und das gesamte Konzept ist im Eimer.

    Der Controller sollte aber tatsächlich so dumm wie möglich sein und – das gleiche gilt aber auch für das Model, denn das soll nur die Daten bereitstellen, die vom Controller angefragt wurden. Es gilt also, das Model so flexibel wie möglich zu gestalten, so dass der Controller auch ebenso einfach und flexibel auf die Daten zugreifen kann.

    In der Praxis hat der Controller aber mehr „Hirn“ als das Model, auch wenn ich weiss dass das nicht immer ganz konsequent ist.

  12. Ich handhabe das Mittlerweile so, das der Controller im Grunde nur ein „Datenabfrager“ beim Modell ist und die Daten dann dem View zur Verfügung stellt. Das View sieht im Grunde nur die Daten und weiss nichts über das Modell. Es hat allerdings Zugriff auf den Controller (in PHP ist das ja mehr oder weniger ein Nebeneffekt wenn das View innerhalb des Controller inkludiert wird) auch wenn man davon keinen Gebrauch machen sollte, weil damit wiederum eine Abhängigkeit View -> Controller bestehen würde.

    Aber insgesamt sollte man das auch nicht päpstlicher als der Papst sehen. Letztlich soll es ja nur helfen die Sichtweise auf ein komplexes System sich zu vereinfachen. Wenn das Framework zu komplex und kompliziert theoretisch ist, geht das auch in die falsche Richtung.

  13. @Daniel:

    „Natürlich ist klar, dass die Daten aus dem Model kommen und diese vom Controller an die View gesendet werden.“

    Da stimme ich dir völlig zu.

    „Der Controller sollte aber tatsächlich so dumm wie möglich sein“
    Da bin ich jedoch anderer Meinung. Bei mir ist das Model der dumme Teil, der Controller verarbeitet Requests, holt die Daten, rechnet, sendet sie an die View, usw. Also denke ich, dass der Controller immer noch der Part mit der meisten Logik ist. Sicherlich gibt es hier andere Umsetzungen, die alle ihre Daseinsberechtigung haben.

    „Der Controller sollte aber tatsächlich so dumm wie möglich sein und – das gleiche gilt aber auch für das Model, denn das soll nur die Daten bereitstellen, die vom Controller angefragt wurden.“
    Wenn sowohl Model als Controller dumm sind, wer denkt dann in deinem MVC?

    @devarni:
    „Es (View) hat allerdings Zugriff auf den Controller (in PHP ist das ja mehr oder weniger ein Nebeneffekt wenn das View innerhalb des Controller inkludiert wird) auch wenn man davon keinen Gebrauch machen sollte, weil damit wiederum eine Abhängigkeit View -> Controller bestehen würde.“

    Daraus schließe ich, dass du deine Templates direkt im Controller inkludierst und die View nicht in einer seperaten Klasse kapselst. Richtig? Bei mir sind Model, View, Controller jeweils eigene Klassen.

    Insgesamt ist und bleibt MVC ein Pattern mit sehr viel Interpretationsspielraum. Aber alles andere wäre ja langweilig 😉

  14. @Daniel

    Eine View Klasse gibt es nicht. Genau. Das ist ein Abstrich oder wenn man so will eine Anpassung die ich bei PHP schon sinnvoll halte. Wenn die Template-Variablen innerhalb des Controllers und einer Methode öffentlich gemacht werden und dort das Template inkludiert wird, hat man eine komplette Datenkapselung. Die Template Daten sind ja nur im Sichtbarkeitsbereich der Methode und damit direkt im inkludierten Template sichtbar.
    Nebeneffekt ist natürlich das man innerhalb des Templates über $this auf den Controller zugreifen kann… Dieses kann man natürlich auch besser lösen, indem man „globale Daten“ über die Anwendungsklasse austauscht (in PHP kann man ja recht einfach „Resourcenklassen“ bauen durch die magischen Funktionen). Das ist dann eine Sache wo das Framework mehr oder weniger helfen kann die Abstraktion zu unterstützen 😉

    Ich denke da schon etwas „nicht komplizierter als nötig“. Mit aller Gewalt eine logische Sicht umzusetzen nur ums sich dann auf die Schulter zu klopfen „ich habe wirklich alles implementiert was dort im Lehrbuch stand“ isses dann auch nicht 😉 Letztlich muss die Anwendung ja auch noch effizient sein und einfach zu warten und zuviele Abstraktionsebenen können da eher kontraproduktiv sein. Hier gehen dann auch oft die Ideen der Informatiktheoretiker und der Informatikpraktiker etwas auseinander. Und deswegen gibt es ja auch dann unterschiedliche Implementierungen (was ja auch völlig in Ordnung ist) 😉

    Es ist auf jedenfall immer wieder interessant welche unterschiedlichen Wege viele Entwickler gehen.

  15. Die Einsparung des Views halte ich wirklich nicht für sinnvoll. Du vermischst da Dinge, die getrennt gehören. Der Controller kümmert sich dann um die Datenverarbeitung und um die Ausgabe. Irgendwie widerstrebt das meinem MVC-Verständnis. Aber wenn du so zurecht kommst, warum nicht? 🙂

    Grundsätzlich bin ich aber deiner Meinung, dass die Theorie nicht zu weit getrieben und die Abstraktion nur da angeawandt werden soll, wo sie auch sinnvoll ist. Meines erachtens ist sie das beim View 🙂

    MfG
    Simon

  16. Also das View ist ja getrennt, der Unterschied ist nur das es nicht noch extra in einer Klasse verkapselt ist aber natürlich sich in einer eigenen Datei befindet. Der Controller lädt ja nur die Ansicht und sorgt für die Bereitstellung der Daten. Die Ansicht würde man in strikter MVC Betrachtung in einer Klasse kapseln. Man bräuchte dann für jede Ansicht bzw. auch jedes Teilfragment (was man ja in PHP recht häufig benutzt) eine eigene von View abgeleitete Klasse.
    Das ist für mich der Punkt wo es dann umständlicher wird als nötig 😉

    Ein IMO sehr gute Implementierung für diese Sichtweise ist übrigens das yii Framework.

  17. „Man bräuchte dann für jede Ansicht bzw. auch jedes Teilfragment (was man ja in PHP recht häufig benutzt) eine eigene von View abgeleitete Klasse.“

    Also ich habe nur eine einzige View-Klasse für jeden Ausgabetyp: HTML, PDF, XML, JSON, usw.

    Und meine HTML-View lädt dann halt die passenden „Templates“ und gibt sie aus.

    yii kenne ich noch nicht, schaue ich mir mal an.

  18. Das Problem dieses MVC ist das es unflexibel ist.
    Ohne Statische Funktionen ist dieses Konzept sinnlos.

    Beispiel:

    Template 1 geladen
    Template 2 geladen <- innerTemplate 4 (Ohne Statische Methode wirds nicht geladen, abhilfe schaft hier nur das Model dem View zu übergeben.)
    Template 3 geladen

  19. Kannst Du deinen Kommentar näher erläutern? Es sind mir zu wenige Informationen, um richtig darauf eingehen zu können. An sich ist MVC sehr flexibel und statische Funktionen brauchte ich auch nicht bzw. nur sehr selten.

    MfG
    Simon

  20. […] erstellt, und weniger weil ich sie wirklich benötigte. Nachdem ich dann noch eine Version im MVC-Stil erstellt hatte (mit Twig als Templating-Engine), und diese erneut verwarf, kam ich zum […]

Hinterlasse einen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

»Informationen zum Artikel

Autor: Simon
Datum: 24.07.2009
Zeit: 15:00 Uhr
Kategorien: OOP & Design Patterns
Gelesen: 82448x heute: 5x

Kommentare: RSS 2.0.
Diesen Artikel kommentieren oder einen Trackback senden.

»Meta