Tutorialserie: Enterprise PHP mit dem Zend Framework [1]
0. Vorwort
Eigentlich war diese Tutorialserie für den Einstieg in einen eigenen Blog gedacht, aber da ich leider zu faul bin selbst einen Blogsystem aufzusetzen findet das halt erstmal in diesem Forum platz. Ich kenne mich zwar mit der Materie aus, habe die Weisheit aber auch nicht mit Löffeln gefressen. Daher bitte jetzt schon um Entschuldigung wenn etwas nicht 100% korrekt sein sollte. In der Softwareentwicklung führen viele Wege nach Rom. Vielleicht schaffe ich es mit den Tutorials sogar, ein paar Vorurteile welche an PHP kleben aus eurem Gedächtnis zu tilgen.
Als Enterpriseumgebung definiere ich Webseiten die kommerziell genutzt werden aber vor allem auch einen gewissen Umfang besitzen. Ein gutes Beispiel währe diese Forensoftware, aber leider ist die Codebasis des vBulletin … ich nenne sie mal "historisch gewachsen". Wer schonmal versucht hat eine Änderung am Forensystem zu schreiben wird mir beipflichten das die Codebasis ziemlicher Müll ist - oder er hat noch keinen agilen PHP Code gesehen (ich beziehe mich auf die 3.x Version).
Nun mal ans Eingemachte: Jeder der schon einmal eine Webseite in PHP erstellt hat und die mit der Zeit ein wenig angeschwollen ist kennt das Problem, dass der Code irgendwann nicht mehr zu warten ist. Ganz zu schweigen vom Einpflegen neuer Features. Löst man einen Fehler kommt es gerne mal vor, dass man durch die ungemeine Komplexität dadurch 2 neue erstellt.
Zitat
99 little Bugs in the Source Code, 99 little Bugs - fix one Bug, recompile and Run - 101 little Bugs in the Source Code…
...
Hauptziel dieser Tutorialserie ist es von solchen eingefahrenen Strukturen weg zu kommen und "agilen" Code zu schreiben. Dazu werden wir uns Tools bedienen wie OOP oder Design Pattern. Deswegen sollte man schon so die eine oder andere Klasse geschrieben haben und zumindest im Ansatz verstehen, was ein Interface ist.
Eine funktionierende Entwicklungsumgebung mit einem Webserver und natürlich PHP (5.2.0+) ist auch Pflicht. Man sollte auch Ahnung haben wie man damit umgeht.
Unter dem Strich: Wer schonmal eine kleine Seite in PHP erstellt hat und sich weiterbilden will ist hier genau richtig.
I. Model / View / Controller (MVC)
MVC ist ein so genanntes 'Software Architekturmuster' oder auch 'Design Pattern'. Am besten versteht man wohl den Sinn wenn man sich ein Strickmuster vorstellt. Viele haben vielleicht schon etwas von Singelton-/ oder Factoryklassen gehört. Auch das sind Pattern in der Softwareentwicklung - man könnte auch "Best Practises" dazu sagen, weil sie eine gute und oft eingesetzte Richtung vorgeben wie man ein Problem lösen kann.
MVC wendet man auf die globale Applikation an und beschreib eine Aufteilung dieser in 3 Teile:
Model
Mit Model beschreibt man die Teile der Applikation die die Busineslogick abbilden - also die eigentliche Verarbeitung von Daten. Ich merke mir nur immer: Model ist alles, was nicht View und nicht Controller ist.
View
Sehr einfach. Der View ist für die Visualisierung an den Benutzer zuständig.
Controller
Der Controller bringt alle Teile der Applikation zusammen und bestimmt welcher Code ausgeführt wird.
Das klingt jetzt erstmal sehr Theoretisch. Aber mit den Codebeispielen später wird einiges einleuchtender. Über MVC könnte man so viel schreiben, aber ich will euch die schnöde Theorie so gut wie möglich ersparen. Da wir gleich ein Framework verwenden werden ist das auch erstmal nicht so wichtig, aber ist gut es mal gehört zu haben.
Damit wir den View und den Controller nicht selbst implementieren müssen, was den Rahmen hier sprengen würde, benutzen wir eine von unzähligen fertigen Implementierungen. Das Zend Fragework. ZF kann noch viel mehr als nur MVC, auf was ich dann hoffentlich noch in weiteren Tutorials eingehen werde. Beispielsweise eine Klasse um einfach mit Zeitangaben zu rechnen, PDF Handling oder eine rudimentäre Template Engine. Bei mir im Büro wird ZF mittlerweile in allen Projekten eingesetzt und hat noch nie enttäuscht. Wer Pear kennt kann sich eine Art "Pear 2.0" mit kompletten OOP unterbau vorstellen.
Damit die Controller Implementierung des ZF greift, muss das mod_rewrite Module (o.ä. bei anderen Servern) aktiviert sein und der AllowOverwrite Schalter muss auf All stehen. Dadurch ist sicher gestellt, dass die Änderungen an der .htacces die wir später vornehmen auch greifen.
Ich bin mir im klaren, dass es auf der ZF Seite ein schönes Quickstart Tutorial gibt. Aber hier wird alles schon durch das neue Zend_Tool geregelt und man bekommt ein fertiges Projekt vorgesetzt. Für den Anfänger ist das nicht das Beste, da die Projekterstellung übergangen wird.
1. Hello World und hübsche URIs
Legt einen neuen Ordner oder ein neues Projekt an und legt darin folgende Ordnerstruktur an. Man kann jetzt vielleicht schon erkennen warum ich zuerst etwas über MVC geschrieben habe. Man erkennt Ordner für die Controller, die Views und die Models.
Der nächste Schritt besteht darin dem Webserver zu sagen, dass er jeden Request auf diesem Host auf die Index.php leiten soll, damit der Controller dann entscheiden kann, wohin dieser Request geleitet wird. Durch mod_rewrite und OllowOverwrite All können wir das bequem in der .htaccess einstellen. Legt dazu im public Ordner die .htaccess Datei an und füllt diese mit folgenden Rewrite Conditions/Rules:
Legt nun euren DocumentRoot oder der VHost der Webservers auf das public Verzeichnis eures Projekts. Bei mir sieht das wie folgt aus:
Als nächstes brauchen wir noch die index.php welche auch unter public liegt. Wir befühlen diese mal mit etwas ganz einfachen damit wir die generelle Funktion testen können:
Hier ein gut gemeinter Tipp am Rande: Lasst in euren PHP Dateien den schließenden PHP-Tag weg. Niemand braucht den und es verhindert ungewollte ausgaben am Ende der Datei. Jeder der schonmal einen mysteriösen Zeilenumbruch in der HTML Ausgabe gesucht hat kann das nachvollziehen.
Ein Aufruf eures Projekts im Browser (bei mir einfach über Localhost) sollte nun die Ausgabe der index.php beinhalten. Nichts neues, aber wer bis hier hin gekommen ist hat das gröbste überstanden.
Was haben wir nun gemacht: Im Grunde keine Hexerei. Eine normale PHP Datei sollte jeder der das hier liest schonmal aufgerufen haben, aber das besondere ist nun, dass jede URI nach dem Host durch die Rewrite Rule auch auf diese index.php umgeleitet wird, sofern es keine Datei ist. Also versucht mal eine URI hinter den Request zu setzen. Das Ergebnis sollte das gleiche sein:
Damit lassen sich nun eine menge toller Sachen machen. URLs wie /index.php?page=mist&user=entropy&session=fa216cddcd66fa&application=BA gehören damit komplett der Vergangenheit an!
2. Installation / Hello Zend Framework
Wie gesagt, das Gröbste ist getan. Jetzt versuchen wir eine Ausgabe zu erstellen, auf die uns der Controller (eigentlich der Router… egal) geleitet hat. Dafür brauchen wir erstmal das Zend Framework, was nichts weiter als eine Sammlung von PHP Klassen ist. Bitte downloaden:
Danach entpackt ihr das ganze in euren library Ordner, damit sich folgende Struktur ergibt:
Wir können nun anfangen unsere neue Zend Umgebung zu initialisieren. Legt dazu im Order applikation eine neue PHP Datei an, und nennt diese Bootstrap.php. Diese wird später alles initialisieren, was wir für unsere Applikation brauchen. Damit diese aber überhaupt gefunden werden kann, brauchen wir erst ein wenig Code in unserer index.php. Bitte beachtet: Ab hier ist jede PHP Datei (ausgenommen index.php) in sich eine eigene Klasse! Keine neuen PHP Datei ohne Klasse erstellen (ist auch nicht mehr nötig).
public/index.php:
Ich denke meine Kommentare im Code sprechen für sich. Sollte bis jetzt noch nicht allzu schwer gewesen sein.
Als nächstes implementieren wir unsere Bootsrap Klasse. Zur Erinnerung: Diese wird uns später so Sachen abnehmen wie die Verbindung zur Datenbank o.ä. Da wir so etwas noch nicht brauchen können wir hier einen leeren Klassenkörper implementieren:
application/Bootstrap.php
Als letztes brauchen wir noch eine rudimentäre Konfigurationsdatei, damit das ZF weis, in welchen Ordnern es die Controller und die Bootstrap Klasse findet. Legen wir dazu eine neue ini Datei im application/configs Ordner an:
application/configs/application.ini
Wir hatten in unsere index.php die APPLICATION_ENV Definition auf development gesetzt. Das bedeutet, dass alle Konfigurationseinträge in der Datei aus dem development Kontext gezogen werden. Wir erben mit development aber die Eigenschaften von production (Gekennzeichnet durch den Doppelpunkt) und überschreiben keine dieser. Wir haben also ein verhalten, als würden wir alle Eigenschaften aus production ziehen. Das wird sehr handlich, wenn man sich z.B. in verschiedenen Kontexten zu verschiedenen Datenbanken verbinden will.
Damit ist die Konfiguration erstmal abgeschlossen. Wenn wir nun die Seite im Browser öffnen, erhalten wir aber eine Fehlernachricht:
Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (error)' in…
Das liegt daran das wir noch keine Controller eingerichtet haben. Um die Umgebung lauffähig zu bekommen benötigen wir mindestens zwei Controller. Den IndexController, welche eine leere Anfrage (host ohne URI http://127.0.0.1) abfängt und einen ErrorController, welcher bei einem Fehlerfall in der Applikation automatisch in die Bresche springt. Legen wir dazu zwei neue Dateien in application/controllers/ an. Eben IndexController.php und ErrorController.php.
application/controllers/ErrorController.php
application/controllers/IndexController.php
Hier noch mal zur Übersicht eine Abbildung der Dateien:
Ähnlich fängt der ErrorController alle Anfragen ab, deren Controller oder Action nicht implementiert ist. Weiterhin wird immer der ErrorController aufgerufen, sollte innerhalb anderer Controller eine Exception geworfen werden.
Damit lässt sich jetzt schon eine Menge anstellen. Auch die schönen verschachtelten Switch/Case blöcke in der index.php gibt es nicht mehr. Neue Seiten lassen sich jetzt bequem anlegen und wir haben ein zentrales Errorhandling, welches ich in späteren Tutorials noch versuchen werde auszubauen. Wir haben nun eine erste funktionsfähige Zend Framework Applikation gebastelt auf die in folgenden Tutorials aufgebaut wird. Der nächste wichtige Schritt währen Views, die man wie eine Art Template Engine berachten kann.
Ich hoffe ich konnte euch den Mund ein wenig wässrig machen. Große PHP Projekte müssen nicht mehr zwangsläufig aus unlesbarem include Wirrwarr bestehen. Viele der in der Softwareentwicklung verbreiteten OOP Pattern lassen sich mittlerweile auch auf PHP anwenden - und mit dem richtigen Framework unterm Hintern ist es nicht mehr schwer, diese zu nutzen. Sicher hat PHP noch seine Schwächen, aber in den letzten Jahren haben diese drastisch abgenommen (HERR! Gib mit einen Strict-Mode für Typensicherheit!).