2. Ein MVC-Entwicklungsansatz für Web/PHP
Hier stellen wir einen Ansatz zur Entwicklung von Web-/PHP-Anwendungen vor, die der MVC-Architektur folgen. Er soll lediglich als Ausgangspunkt dienen. Der Leser sollte ihn an seine eigenen Vorlieben und Bedürfnisse anpassen.
- Wir beginnen damit, alle Ansichten der Anwendung zu definieren. Dabei handelt es sich um die Webseiten, die dem Benutzer angezeigt werden. Bei der Gestaltung der Ansichten nehmen wir die Perspektive des Benutzers ein. Es gibt drei Arten von Ansichten:
- das Eingabeformular, das dazu dient, Informationen vom Benutzer zu erfassen. Es enthält in der Regel eine Schaltfläche, um die eingegebenen Informationen an den Server zu übermitteln.
- Die Antwortseite, die ausschließlich dazu dient, dem Benutzer Informationen bereitzustellen. Diese enthält oft einen oder mehrere Links, über die der Benutzer die Anwendung auf einer anderen Seite weiter nutzen kann.
- die gemischte Seite: Der Controller hat dem Client eine Seite mit von ihm generierten Informationen gesendet. Dieselbe Seite wird vom Client verwendet, um dem Controller neue Informationen vom Benutzer zu übermitteln.
- Jede Ansicht generiert eine PHP-Seite. Für jede dieser Ansichten
- entwerfen wir das Layout der Seite
- legen wir fest, welche Teile davon dynamisch sind:
- die für den Benutzer bestimmten Informationen, die vom Controller als Parameter an die PHP-Ansicht übergeben werden müssen. Eine einfache Lösung sieht wie folgt aus:
- Der Controller legt die Informationen, die er einer Ansicht V bereitstellen möchte, in einem Dictionary $dResponse ab
- Der Controller zeigt die Ansicht V an. Wenn dies der Quelldatei V.php entspricht, erfolgt diese Anzeige einfach durch die Anweisung include V.php.
- Die vorstehende Einbindung ist eine Code-Einbindung innerhalb des Controllers. Auf das vom Controller gefüllte $dResponse-Dictionary kann der Code in V.php direkt zugreifen.
- Die Eingabedaten, die zur Verarbeitung an das Hauptprogramm übermittelt werden müssen. Diese Daten müssen Teil eines HTML-Formulars sein (Tag <form>).
- die für den Benutzer bestimmten Informationen, die vom Controller als Parameter an die PHP-Ansicht übergeben werden müssen. Eine einfache Lösung sieht wie folgt aus:
- Wir können die Ein- und Ausgabe für jede Ansicht schematisch darstellen
![]() |
- Eingaben sind die Daten, die der Controller an die PHP-Seite übergeben muss
- Ausgaben sind die Daten, die die PHP-Seite dem Anwendungscontroller bereitstellen muss. Sie sind Teil eines HTML-Formulars, und der Controller ruft sie mithilfe einer Operation wie $_GET["param"] (GET-Methode) oder $_POST["param"] (POST-Methode) ab.
- Häufig ist die endgültige Seite, die an den Client gesendet wird, keine einzelne Ansicht, sondern eine Zusammensetzung aus Ansichten. Die an einen Benutzer gesendete Seite könnte beispielsweise wie folgt aussehen:
![]() |
Bereich 1 kann ein Kopfzeilenbanner sein, Bereich 2 ein Menü-Banner und Bereich 3 ein Inhaltsbereich. In PHP lässt sich diese Zusammensetzung mit dem folgenden HTML/PHP-Code realisieren:
<table>
<tr>
<td><?php include zone1.php ?></td>
</tr>
<tr>
<td><?php include zone2.php ?></td>
<td><?php include zone3.php ?></td>
</tr>
</table>
Sie können diesen Code dynamisch gestalten, indem Sie Folgendes schreiben:
<table>
<tr>
<td><?php include $dReponse['urlZone1'] ?></td>
</tr>
<tr>
<td><?php include $dReponse['urlZone2'] ?></td>
<td><?php include $dReponse['urlZone3'] ?></td>
</tr>
</table>
Diese Ansichtszusammensetzung kann das einzige Format der an den Benutzer gesendeten Antwort sein. In diesem Fall muss jede Antwort an den Client die drei URLs festlegen, die in die drei Zonen geladen werden sollen, bevor die Antwortseite angezeigt wird. Wir können dieses Beispiel verallgemeinern, indem wir uns vorstellen, dass es mehrere mögliche Vorlagen für die Antwortseite gibt. Die Antwort an den Client muss daher:
- die zu verwendende Vorlage bestimmen
- die darin einzubindenden Elemente festlegen
- die Anzeige der Vorlage anfordern
- Wir werden den PHP/HTML-Code für jede Antwortvorlage schreiben. Der Code ist in der Regel einfach. Der Code für das obige Beispiel könnte wie folgt aussehen:
<?php
// initializations for testing without a controller
...
?>
<html>
<head>
<title><?php echo $dReponse['titre'] ?></title>
<link type="text/css" href="<?php echo $dReponse['style']['url'] ?>" rel="stylesheet" />
</head>
<body>
<table>
<tr>
<td><?php include $dReponse['urlZone1'] ?></td>
</tr>
<tr>
<td><?php include $dReponse['urlZone2'] ?></td>
<td><?php include $dReponse['urlZone3'] ?></td>
</tr>
</table>
<body>
</html>
Wann immer möglich, verwenden wir ein Stylesheet, damit wir das „Aussehen“ der Antwort ändern können, ohne den PHP-/HTML-Code ändern zu müssen.
- Wir werden den PHP/HTML-Code für jede Basisansicht schreiben. Meistens wird er folgende Form haben:
<?php
// a few initializations may be necessary, particularly in the debugging phase
...
?>
<balise>
...
// here we'll try to minimize the php code
</balise>
Beachten Sie, dass eine Basisansicht in eine Vorlage eingebettet ist. Ihr HTML-Code ist in den Code der Vorlage integriert. Meistens enthält die Vorlage bereits die Tags <html>, <head> und <body>. Daher findet man diese Tags selten in einer Basisansicht.
- Wir können nun damit fortfahren, die verschiedenen Antwortvorlagen und Basisansichten zu testen
- Jede Antwortvorlage wird getestet. Wenn eine Vorlage den Namen modele1.php trägt, rufen wir die URL http://localhost/chemin/modele1.php über einen Browser auf. Die Vorlage erwartet Werte vom Controller. Hier rufen wir sie direkt auf, anstatt über den Controller. Die Vorlage erhält die erwarteten Parameter nicht. Um das Testen dennoch zu ermöglichen, initialisieren wir die erwarteten Parameter manuell in der PHP-Seite der Vorlage mithilfe von Konstanten.
- Jedes Modell wird getestet, ebenso wie alle Basisansichten. Dies ist auch der Zeitpunkt, um die ersten Elemente der verwendeten Stylesheets zu entwickeln.
- Als Nächstes schreiben wir die Anwendungslogik:
- Der Controller, also das Hauptprogramm, verarbeitet in der Regel mehrere Aktionen. Die auszuführende Aktion muss in den empfangenen Anfragen definiert sein. Dies kann mithilfe eines Anfrageparameters erfolgen, den wir hier `action` nennen:
- Wenn die Anfrage von einem Formular stammt (<form>), kann dieser Parameter ein versteckter Formularparameter sein:
<form ... action="/C/main.php" method="post" ...>
<input type="hidden" name="action" value="uneAction">
...
</form>
- (Fortsetzung)
- Wenn die Anfrage über einen Link erfolgt, können Sie dies wie folgt konfigurieren:
Der Controller kann zunächst den Wert dieses Parameters auslesen und anschließend die Bearbeitung der Anfrage an ein Modul delegieren, das für die Abwicklung dieser Art von Anfragen zuständig ist. Hier gehen wir davon aus, dass alles von einem einzigen Skript namens main.php gesteuert wird. Wenn die Anwendung die Aktionen action1, action2, …, actionx verarbeiten muss, können Sie für jede Aktion eine eigene Funktion innerhalb des Controllers erstellen. Bei einer großen Anzahl von Aktionen kann dies jedoch zu einem „Dinosaurier“-Controller führen. Alternativ kann man Skripte action1.php, action2.php, ..., actionx.php erstellen, die für die Bearbeitung der jeweiligen Aktion zuständig sind. Der Controller, der mit der Bearbeitung der Aktion actionx beauftragt ist, lädt den Code einfach aus dem entsprechenden Skript mithilfe einer Anweisung wie include „actionx.php“ ein. Der Vorteil dieser Methode besteht darin, dass Sie außerhalb des Controller-Codes arbeiten. Jedes Mitglied des Entwicklungsteams kann somit relativ unabhängig an dem Skript arbeiten, das eine actionx-Aktion bearbeitet. Das Einbinden des Codes aus dem Skript actionx.php in den Controller-Code zur Laufzeit hat zudem den Vorteil, dass die Menge des in den Speicher geladenen Codes reduziert wird. Es wird nur der Code zur Abwicklung der aktuellen Aktion geladen. Diese Codeeinbindung bedeutet, dass Controller-Variablen mit denen im Aktionsskript in Konflikt geraten können. Wir werden sehen, dass wir Controller-Variablen auf einige wenige, genau definierte Variablen beschränken können, die dann in den Skripten vermieden werden sollten.
- Wir werden systematisch versuchen, die Geschäftslogik oder den Code für den Zugriff auf persistente Daten in separate Module auszulagern. Der Controller fungiert als eine Art Teamleiter, der Anfragen von seinen Clients (Web-Clients) entgegennimmt und diese von den am besten geeigneten Entitäten (den Geschäftsmodulen) ausführen lässt. Beim Schreiben des Controllers legen wir die Schnittstelle der zu schreibenden Geschäftsmodule fest. Dies gilt, wenn diese Geschäftsmodule erst erstellt werden müssen. Wenn sie bereits existieren, passt sich der Controller an die Schnittstelle dieser vorhandenen Module an.
- Wir werden das Grundgerüst der vom Controller benötigten Geschäftsmodule schreiben. Wenn der Controller beispielsweise ein `getCodes`-Modul verwendet, das ein Array von Strings zurückgibt, können wir zunächst einfach schreiben:
- Anschließend können wir mit dem Testen des Controllers und der zugehörigen PHP-Skripte fortfahren:
- Der Controller, die Aktionsskripte, Modelle, Ansichten und Ressourcen, die von der Anwendung benötigt werden (Bilder usw.), werden im DC-Ordner abgelegt, der dem C-Kontext der Anwendung zugeordnet ist.
- Sobald dies erledigt ist, wird die Anwendung getestet und die anfänglichen Fehler werden behoben. Wenn main.php der Controller und C der Anwendungskontext ist, rufen wir die URL http://localhost/C/main.php auf. Am Ende dieser Phase ist die Anwendungsarchitektur betriebsbereit. Diese Testphase kann eine Herausforderung darstellen, da nur wenige Debugging-Tools zur Verfügung stehen, wenn Sie keine fortgeschrittenen Entwicklungsumgebungen verwenden, die in der Regel kostenpflichtig sind. Sie können echo „message“-Anweisungen verwenden, die in den an den Client gesendeten HTML-Stream schreiben und somit auf der vom Browser angezeigten Webseite erscheinen.
- Schließlich schreiben wir die vom Controller benötigten Business-Klassen. Dies umfasst in der Regel die Standardentwicklung einer PHP-Klasse, die normalerweise unabhängig von einer Webanwendung ist. Sie wird zunächst außerhalb dieser Umgebung getestet, beispielsweise mithilfe einer Konsolenanwendung. Sobald eine Business-Klasse geschrieben wurde, integrieren wir sie in die Bereitstellungsarchitektur der Webanwendung und testen ihre korrekte Integration. Auf diese Weise verfahren wir für jede Business-Klasse.

