Andreas Korthaus: DAO / MVC-Design in (PHP-)Webapplikationen - sinnvoll?

Beitrag lesen

Hallo!

Ich habe mich die letzten Tage durch einige sehr interessante Webseiten/Artikel gearbeitet, unter anderem:

http://www.phppatterns.com/
http://www.phparch.com/issue.php?mid=9
http://www.phparch.com/sample.php?mid=10
http://php.weblogs.com/ADODB
http://www.phpconference.com/downloader/downloader.php?CatID=0&NewsID=367
http://talks.php.net/
...

Kann ich nur empfehlen, unglaublich viele sehr interessante Artikel über "professionelle Webapplikationen mit PHP" wenn ich es mal so umschreiben will.
Und zwar stehe ich gerade vor dem ersten größeren "Refactoring" einer größeren eigenen PHP-Applikation wo aufgrund von Zeitdruck das Design ein wenig gelitten hat - um es mal so auszudrücken ;-)
Von der Uni her musste ich mich die letzte Zeit auch ein wenig mit Java beschäftigen, und da kommt man irgendwann zwangsläufig mit Dingen wie J2EE in Kontakt, und auch mit interessanten Frameworks für Webapplikationen wie Jakarta Struts von der Apache Foundation und anderen. Jetzt war ich immer davon ausgegangen, dass es sowas für PHP nicht gibt, aber dank der obigen Artikel habe ich gemerkt, dass es sowas sehr wohl gibt, und zwar wie Sand am Meer (Phrame, Mojavi, php.MVC um nur ein paar bekanntere zu nennen). Diese Frameworks versuchen zumeist die Konzepte von Struts in PHP zu übersetzten.

Und ich frage mich jetzt - wie sinnvoll ist das? Denn PHP ist ja nicht Java, und MVC kommt ja eigentlich von der GUI-Programmierung, was ja nicht direkt mit Webapplikationen vergleichbar ist (z.B. haben GUIs keinen Webserver der von alleine das angeforderte Script starten kann...). Nach Lesen einiger interessanter Diskussionen haben sich 2 Meinungen herauskristallisiert, die einen finden das ganz prima mit Framewoks wie Phrame zu arbeiten, die anderen sagen das ist Quatsch, man brauche keinen Controller und kein Action-Mapping, dafür hätten wir ja den Webserver...

Ich mache zur Zeit eine Art Mischmasch, ich verwende ein Script welches alle Libs und Einstellungen läd, welches per Mod-Rewrite bei jedem Request geladen wird und entsprechend dem eigentlichen Request dann ein Modul(Verzeichnis) und dort ein Script läd, ein Request sieht etwas so aus:

/[modulname]/[scriptname]

und alles weiter kommt dahinter als Parameter. (Wobei ich auf mod_rewrite aufgrund der Größe des Moduls lieber verzichten würde...)

Das Script was dann geladen wird weiß was zu tun ist und läd dann notwendige Klassen und "macht dann irgendwas" damit.
Was ist Eure Meinung dazu? Hat es einen Sinn wie bei Struts oder Phrame zentral alle "Actions", also alle Requests die möglich sein sollen zentral zu definieren? Ich finde das sehr unpraktisch, vor allem auch weil ich eine eigene Plugin-Architektur habe, wo Plugins kpl. in einem eigenen Ordner liegen und nicht in allen möglichen Verzeichnissen der Applikation Änderungen vornehmen sollen. Man könnte zwar auch per php.ini per auto-prepend(oder wie das heißt) ein Script  vor jedem Request laden, welches dann die Konfigurationen... durchführt, also dass über den Webserver immer echte Pfade aufgerufen werden, nur ist das dann etwas schwierig wenn die ganzen Plugins mit allen Unterverzeichnissen innerhalb es doc-root liegen, das mag ich z.B. nicht so.

Wie seht Ihr das, ist ein MVC-Design in einer PHP-Webapplikation sinnvoller?

Und noch eine Frage, ich verwende zwar eine Datenbank-Abstraktion, aber man hört/liest oft, man solle noch eine DAO(Data Access Object) - Schicht zwischen Datenbank-Abstraktion und der eigentlichen Business-Logik haben. Was haltet hier hiervon?

Mal am Beispiel eines Produktkataloges, sagen wir mal ich habe eien Tabelle "products", die dann die Grunddaten der Produkte enthält, z.B. HerstellerID, Preis und Titel. Dann haben wir noch spezielle Tabellen, sagen wir mal für "computer", die dann produktspezifische Daten enthält.

Jetzt sagen wir mal ich habe ein HTML-Formular welches die Daten eines Computers enthält, sowohl die aus der Tabelle products als auch aus computer. Dieses Formular schicke ich jetzt ab.

Bei mir erzeugt das dann so einen Request: /products/edit?prod_id=123&typ=2&price=22,99...

Das führt dazu dass das "edit.php" Script aus dem Modul-Verzeichnis "products" geladen wird (include).
Dies hat dann einen Switch und weiß dass bei typ=2 die Klasse "Computer" geladen wird, die von "Products" erbt.

Das Script edit.php macht dann also sowas:
include('Cpmputer.class.php');
$computer = new Computer($_REQUEST['prod_id']);

und dann

$computer->setPrice($_REQUEST['price']);
$computer->setCPU($_REQUEST['cpu']);
...

und am Ende

$computer->storeData();

Diese Methode muss ich dann überall einbauen, da sich das immer unterscheidet, und die sieht dann so aus:

function storeData() {
  global $db;
  $sql = "UPDATE
            products
          SET
            price=$this->price,
            ...
          WHERE
            prod_id=$this->id;
  $db->query($sql);
  $sql = "UPDATE
            computer
          SET
            cpu=$this->cpu,
            ...
          WHERE
            prod_id=$this->id";

}

So wird das ganze dann persistiert (ist jetzt natürlich etwas vereinfacht, ohne Validierung...).

Meine Frage ist jetzt, macht Ihr das vergleichbar, oder habt Ihr tatsächlich noch eine DAO-Schicht dazwischen, wie es J2EE ja z.B. durch Beans oder EJBs vorsieht?

Manchmal wird ja auch eine extra Klasse für jedes Objekt gebaut, die für das Speichern zuständig ist, also wäre die Methode storeData() nicht in "Computer" integriert sondern z.B. in ComputarDataStorage, wo  sich diese Methode dann die Daten über getPrice()... Methoden dann die Daten holt und in die DB schreibt. Findet Ihr das sinnvoll?
Genauso beim Lesen von Daten, würdet Ihr das auch von der eigentlichen "Business Logik" Klasse, also "Computer" abkapseln und hier jeweils eine eigen Klasse schreiben die die Daten aus der DB holt und in die Klasse "Computer" schreibt?

Viele Grüße
Andreas