PHP - MVC oder Wie erstelle ich ein modernes Framework

Thom-

Grünschnabel
Hallo zusammen,

in meiner Freizeit habe ich schon einige Projekte in PHP erstellt, auch ein komplettes Portal + Forum usw.
Nach 2005 habe ich viel in C# programmiert und so auch ein wenig das OOP lieben gelernt. Ich versuche momentan mich ein wenig in moderner PHP Entwicklung schlau zu machen.

In meiner jetzigen Arbeitsstelle bin ich als Entwickler für das Intranet tätig, welches aus einem zugegeben uralten Framework (seit 1998 entwickelt) besteht.
Ich kann von Glück sagen, dass irgendwann zumindest auf PHP4 umgesattelt wurde, aber der Code an sich ist doch schon relativ veraltet.

Mich interessiert es jetzt wie man eurer Meinung nach heutzutage ein modernes Framework für eine Intranet Umgebung in einer Firma entwickeln würde. Ich versuche meinerseits immer modern zu entwickeln und weiß auch, dass ich das Firmenintranet wohl nie komplett umschmeißen kann und darf, aber dennoch möchte ich nicht dumm sterben und mich immer schön weiterbilden.

Ich habe mich in das MVC Modell eingelesen und mir überlegt wie man soetwas in PHP umsetzen würde.

Kurzbeschreibung des unteren Textes:
Wie würdet Ihr, eurer Meinung nach, ein modernes Framework aufbauen, welches mehreren Entwicklern die Möglichkeit zur Entwicklung von einem Intranet bieten würde?


Ich erläutere mal, warum ich das für ein Intranet nicht so simpel empfinde, wie evtl. für ein Blog o.ä.:


Ich habe mitbekommen, dass der Controller ja zuständig wäre für die Interaktion mit dem Benutzer (also z.B. eine eintragen.php).
Der Viewer wäre ja bei PHP der geläufigen Meinung nach das Template.

Jetzt das Modell. Oft wird als Beispiel ein Blogpost genommen. Man hätte also ein Model namens Blog (bzw. blogPost o.ä.), welches dann Methoden wie insertPost() o.ä. hätte.

Ich könnte also zum jetzigen Zeitpunkt wohl einen MVC Konformen Blog erstellen.

Aber:
Wie würde man jetzt für eine Firma (oder auch für das Blog selber von mir aus) einen Report nach dem MVC Modell erstellen?

Eine simple Auswertung nach von mir aus Einträgen und Benutzerkommentaren o.ä..

Gut, als Template (Viewer) würde man also das Aussehen des Reports definieren.
Der Controller würde wohl eine Filtermöglichkeit geben (nach Zeitraum z.B.).

Jetzt die Preisfrage: Wie würde da ein Model aussehen?
Extra ein Model pro Report? Mit Methoden wie display() und prepare()? Dazu einer Variable namens $query, welche dann die komplexe Datenbankabfrage in ein Array speichert?
Eine Methode display() wäre ja meiner Ansicht nach Quatsch, da das ja über das Template laufen muss.
Also müsste man im Template auf das Datenarray des Models zugreifen und im Template die ganze Logik verankern (wenn Minusbetrag, dann Rot, wenn X und Y dann evtl. Daten von wo anders herausziehen)
Aber für was dann der ganze Aufwand? Wenn schon ohnehin Logik im Template vorhanden ist, für was dann ein Template?

Irgendwie habe ich da einen kleinen Hirnknoten...

Mal angenommen man erstellt im Laufe der Zeit unter verschiedenen Entwicklern 60-100 Reports.
Muss jetzt jeder Entwickler pro Report einmal ein Template erstellen, dann ein Modell zu seinem Report (nach Schema F, also prepare() und display()?)
Dazu noch eine Controller Page und das wars?

Bisher habe ich einen Ordner namens Report<nummer> und darin eine Filter.php und Main.php.
Worin ist dann die Verbesserung? (Außer, dass nun 3 statt 2 PHP Files erstellt werden müssen)

Andere Gedanken zur modernen Entwicklung:
In dem jetzigen Framework gibt es eine Funktion namens text().
Jegliche Ausgabe wird über diese Funktion ausgeführt. Die Funktion text() sucht, falls eine andere Sprache als Deutsch eingestellt ist, nach einer möglichen Übersetzung und gibt dann für die einzelnen text-Bausteine die Übersetzung aus.
Wenn ich nun mit Templates arbeite ist da ja nicht mehr möglich.
Momentan kann ein User (mit einer entsprechenden Rolle) frei wählbar den "Translate" Button drücken und einen dieser text() Aufrufe übersetzen. In der DB wird die Translation dazu gespeichert und dann wird beim nächsten Aufruf der übersetzte Text angezeigt. Klingt langsam und unperformant, aber funktioniert erstaunlicherweise seit Jahren wunderbar.

Wie würde man sowas MVC konform entwickeln? Jeglicher Text im Template müsste dann ja irgendwie dynamisch werden? Ich habe dazu irgendwie gar keine Idee.


Vielleicht hat mir jemand auch ein wenig Literatur dazu, das würde mir schon ungemein helfen.

Gruß
-Thomas
 
Nach 2005 habe ich viel in C# programmiert und so auch ein wenig das OOP lieben gelernt.
Was ich stellenweise wahrnehme (vor allem im Bereich Enterprise Solutions) ist, dass einige Sachen um der Objektorientierung Willen völlig verkompliziert und abstrahiert werden, bis der Sinn und Nutzen von OOP kaum bis nicht mehr vorhanden ist.

Sofern du mit PHP arbeiten möchtest, solltest du weniger auf spezielle Design Patterns und Schemen zurückgreifen, die in C# oder Java gebräuchlich sind. Die schwache Typisierung und dergleichen werden dir sonst schnell ein Bein stellen. Des Weiteren leben zB Java Servlets gerade von der Container-Integration, welche in PHP so nie erreicht werden kann.

Mich interessiert es jetzt wie man eurer Meinung nach heutzutage ein modernes Framework für eine Intranet Umgebung in einer Firma entwickeln würde. Ich versuche meinerseits immer modern zu entwickeln und weiß auch, dass ich das Firmenintranet wohl nie komplett umschmeißen kann und darf, aber dennoch möchte ich nicht dumm sterben und mich immer schön weiterbilden.
Wie auch das Rad muss ein solides Framework nicht ständig neu erfunden werden. Vorrangig auf den Web-(GUI-)Betrieb ausgelegt, sind das Zend Framework Code Igniter oder auch CakePHP trotzdem nicht zu verachten. Anscheinend geht es dir wohl auch vor allem darum eine sinnvolle "Web" (Intranet) Oberfläche anbieten zu können, und dafür halten diese Frameworks allesamt die passenden Werkzeuge bereit.

Wie würdet Ihr, eurer Meinung nach, ein modernes Framework aufbauen, welches mehreren Entwicklern die Möglichkeit zur Entwicklung von einem Intranet bieten würde?
Ein solides, bestehendes Framework mit einer sinnvollen Dokumentation sollte die Grundlage bieten. Sofern Bedarf zur Erweiterung und Anpassung besteht, sind Klassen in PHP vererbbar, und die Quellcodes der oben genannten FWs können entsprechend ihrer Lizenzen bearbeitet werden.
Ein komplett eigenes Framework ist meiner Meinung nach in den seltensten Fällen sinnvoll, und frisst immense Resourcen.

Ich habe mitbekommen, dass der Controller ja zuständig wäre für die Interaktion mit dem Benutzer (also z.B. eine eintragen.php).
Der Viewer wäre ja bei PHP der geläufigen Meinung nach das Template.
Über ersteres kann man sich (wie über so vieles) gut streiten. Es hängt letztenendes vom Framework ab, was wo wie verarbeitet wird.
Das View ist, wie du richtig bemerkt hast, die Komponente, welche sich sozusagen um die Darstellung der Models und des Drumherums kümmert.

Jetzt das Modell. Oft wird als Beispiel ein Blogpost genommen. Man hätte also ein Model namens Blog (bzw. blogPost o.ä.), welches dann Methoden wie insertPost() o.ä. hätte.
Zum Thema Models in PHP habe ich bisher wenig einheitliches lesen können. Auch wenn es stellenweise (bewusst) nicht MVC-konform ist, verwalte ich für meine Zwecke zwei Arten von Models. Einerseits sind das Datenbanktabellen-Modelle, welche ORM-ähnliche Logik implementieren (was du im Beispiel mit "BlogPost::insertPost()" anführst), andererseits aber eher C-Struct-ähnliche Konstrukte mit Java-Standardbeans-ähnlicher Gestaltung, die wirklich nur Daten halten und zurückgeben.

Wie würde man jetzt für eine Firma (oder auch für das Blog selber von mir aus) einen Report nach dem MVC Modell erstellen?

Eine simple Auswertung nach von mir aus Einträgen und Benutzerkommentaren o.ä..
Nicht das Framework kümmert sich um die Models und Controller, sondern der / die Entwickler. Was hindert dich daran Datenbank-Views anzulegen, oder komplexere Queries im Controller (oder in einer Table-Model-Methode) auszuführen? Dafür sind die Teile schließlich da, um die Geschäftslogik zu verwalten und Models und Views zusammenzuführen.

Jetzt die Preisfrage: Wie würde da ein Model aussehen?
Extra ein Model pro Report? Mit Methoden wie display() und prepare()? Dazu einer Variable namens $query, welche dann die komplexe Datenbankabfrage in ein Array speichert?
Ein triviales Beispiel mit dem ZF könnte in der ControllerAction etwa so aussehen:
PHP:
$table = new myZend_Db_Table();
$stmt  = $table->select()->from($table, array('myCol'));

if (isset($_REQUEST['filter'])) {
	$stmt->where('mySecondCol = ?', $_REQUEST['filter']);
}

$results = $stmt->query()->fetchAll();
Etwas praxisnäher:
PHP:
$table = new myReports_Table();
/*
 * myReports_Table::getReports($filter = null) {
 *     $stmt = $this->select()->colums('myCol');
 *     if (null !== $filter) {
 *         $stmt->where('mySecondCol = ?, $filter);
 *     }
 *     return $stmt;
 * }
 */
$results = $table->getReports( isset($_REQUEST['filter']) ? $_REQUEST['filter'] : null )
	->query()->fetchAll();

Eine Methode display() wäre ja meiner Ansicht nach Quatsch, da das ja über das Template laufen muss.
Meiner Meinung nach sollte - wenn überhaupt - der Controller eine solche Methode implementieren, welche zweckmäßig vom Dispatcher (Front Controller) aufgerufen wird.

Also müsste man im Template auf das Datenarray des Models zugreifen und im Template die ganze Logik verankern (wenn Minusbetrag, dann Rot, wenn X und Y dann evtl. Daten von wo anders herausziehen)
Aber für was dann der ganze Aufwand? Wenn schon ohnehin Logik im Template vorhanden ist, für was dann ein Template?
Du verwechselst Darstellungs- mit Geschäftslogik. Dass eine Zahl rot dargestellt werden soll ist für den Controller so lange irrelevant, wie er mit der Information nichts anfangen muss. Wie die Ausgabe formatiert ist, und was in welcher Farbe dargestellt werden soll, das alles ist Darstellungslogik und gehört entsprechend in die Views.
Andererseits wäre es bei den von dir angesprochenen Reports (abhängig vom Zweck) durchaus sinnvoll zu wissen, ob beispielsweise im Gegensatz zum Vormonat Gewinne erwirtschaftet wurden. Die Feststellung und Festlegung gehört in diesem Fall zur Geschäftslogik, also in den Controller.

Mal angenommen man erstellt im Laufe der Zeit unter verschiedenen Entwicklern 60-100 Reports.
Muss jetzt jeder Entwickler pro Report einmal ein Template erstellen, dann ein Modell zu seinem Report (nach Schema F, also prepare() und display()?)
Dazu noch eine Controller Page und das wars?
Ich kann mangels Erfahrung und Ahnung nicht einordnen, was das für Reports sind, in den meisten Fällen sollte man es sich aber nicht zu schwierig machen und stattdessen dynamisch skalierbare Darstellungslogik verwenden um verschiedene Implementierungen über eine View darstellen zu können. Sind hingegen spezielle Anforderungen an die Templates gestellt, sollten diese entsprechend auch individuell eingepflegt werden. Gerade das ist einer der View-Controller-Vorteile: Darstellung und Geschäftslogik können unabhängig voneinander betrachtet werden . Lediglich sollte das View natürlich die Models und Daten, die vom Controller bereitgestellt werden auch verarbeiten können. :)

Bisher habe ich einen Ordner namens Report<nummer> und darin eine Filter.php und Main.php.
Worin ist dann die Verbesserung? (Außer, dass nun 3 statt 2 PHP Files erstellt werden müssen)
Durch die Abstraktion der einzelnen Bestandteile vermeidest du einen ansonsten benötigten linearen Skalieraufwand. Des Weiteren wird die ganze Angelegenheit wartbarer, da es im besten Fall bei den drei Dateien bleibt, wovon du meist (wenn überhaupt) lediglich eine bearbeiten musst.

In dem jetzigen Framework gibt es eine Funktion namens text().
Jegliche Ausgabe wird über diese Funktion ausgeführt. Die Funktion text() sucht, falls eine andere Sprache als Deutsch eingestellt ist, nach einer möglichen Übersetzung und gibt dann für die einzelnen text-Bausteine die Übersetzung aus.
Wenn ich nun mit Templates arbeite ist da ja nicht mehr möglich.
Mit den entsprechenden Helferlein ist es gar nicht mehr nötig! Statt die Texte statisch in die Templates zu packen, kann man auf Platzhalter, View-Helfer, Translatoren, etc zurückgreifen. Auch hier bietet beispielsweise das ZF eine extrem nützliche Schnittstelle. Der (vorkonfigurierte) Translator wird lediglich dem View übergeben, welcher diesen dann den Templates bereitstellt. Das könnte dann so aussehen:
PHP:
// im Controller
$translator = Translator::factory('xml', '/my/translations.xml');
$translator->setStandardLanguage($_REQUEST['pref_language']);
$this->view->assign('translator', $translator);

// im View-Template
<h1><?php echo $this->escape($this->translator->getPhrase('section_mySection')); ?></h1>
<p><?php echo $this->escape($this->translator->getPhrase('welcome_message')); ?></p>

Momentan kann ein User (mit einer entsprechenden Rolle) frei wählbar den "Translate" Button drücken und einen dieser text() Aufrufe übersetzen. In der DB wird die Translation dazu gespeichert und dann wird beim nächsten Aufruf der übersetzte Text angezeigt. Klingt langsam und unperformant, aber funktioniert erstaunlicherweise seit Jahren wunderbar.
Gegen Performanceprobleme helfen Komponenten wie eAccelerator und MemCache, Query-Optimierung, Caching, ... OOP in PHP frisst verhältnismäßig viele Resourcen, wenn man es drauf anlegt (oder auch nicht). Grundlegendes Caching und eAccelerator sollten deshalb auch für Intranet-Anwendungen verwendet werden. Beispielsweise ist es effektiver den Translator samt Phrasen zu Cachen statt bei jedem Request erneut die Translation-Source zu lesen und zu interpretieren.

Wie würde man sowas MVC konform entwickeln? Jeglicher Text im Template müsste dann ja irgendwie dynamisch werden? Ich habe dazu irgendwie gar keine Idee.
Einen möglichen und hoffentlich verständlichen Ansatz habe ich dir hoffentlich mit dem letzten Schnipsel bereitstellen können. Man könnte das ganze noch weiter treiben und die Semantik von der bisherigen HTML-Auszeichnung entkoppeln durch verschiedene Templates, oder sogar durch Render-Fabriken (ähnlich zu JSTL), welche lediglich an Hand eines Schlüssels für das gewünschte Ausgabeformat die Daten formatieren.

Hoffe, du kannst mit dem Text ein wenig was anfangen - Für Fehler jeglicher Art trage ich keine Verantwortung :)
 
Als aller erstes: schreibe kein eigenes Framework! Nur du (oder die Firma, wo du arbeitest) wird es verwenden und es wird das Rad zum millionsten Male neu erfunden! Das ist einfach unnötig, da es viel Zeit kostet, nie richtig getestet wird und vor allem Tester Fehler! Weitere Code Contributor sind auch nicht zu vernachlässigen.

Ich selbst arbeite jetzt seit über anderthalb Jahren mit dem Zend Framework und bin total begeistert davon. Es lässt sich sehr gut für private Zwecke einsetzen aber auch als für Enterprise Plattformen. Zudem hat man die völlständige Code-Controlle (anders als bei CakePHP), was ich auf jeden Fall bevorzuge. In den nächsten Tagen soll die Version 1.8.0 erscheinen, die einige Änderungen enthält und dem Entwickler weiter das Leben vereinfachen. Die Dokumentation sowie ein Preview Release sind aber schon online.

Falls du weitergehende Fragen hast, kannst du auch gerne mal in der deutschen Community unter http://www.zfforum.de reinschauen. Ich selbst bin dort unter dem Nick "DennisBecker" angemeldet. Ansonsten kann ich dir auch gerne eine PM mit wieteren Links zum Thema ZF an dich schicken.
 
Zurück