Extension-Entwicklung neu durchdacht: TYPO3 und das MVC- Konzept
Das ursprünglich von Trygve Reenskaug als „Seeheim-Modell“ [1] beschriebene MVC-Konzept wurde anfänglich vor allem für Benutzeroberflächen in der Programmiersprache „Smalltalk“ genutzt. Das war wohl in den 70ern und seit dem hat es sich als Standard bei komplexen Softwaresystemen etabliert. Die Kommunikation erfolgt bei Desktop-Anwendungen meist über „Events“. Das kann zum Beispiel ein Schieberegler, ein Mausklick oder die Auswahl einer Schaltfläche sein. In Webanwendungen spricht man meist von "Actions“. Die Trennung in Controller (Steuerung der Anwendung durch den User), Model (Programmlogik/Datenquelle) und View (Ausgabe der Daten) ermöglicht das Aufteilen der Anwendung in unabhängige Klassen und deren Austauschbarkeit, bei gleichzeitiger Erhöhung der Übersichtlichkeit der Anwendung. Meist spielen ein View und ein Controller zusammen, wohingegen das Model nichts von beiden weiß. Bezogen auf Webanwendungen verwaltet das Model also die Daten, der View stellt diese in HTML dar, und der Controller steuert beide aufgrund der empfangenen GET/POST-Parameter, welche ja wiederum vom View (zum Beispiel in Form eines Formulars) bereitgestellt wurden. Das MVC-Konzept ermöglicht so, durch seine klare Strukturierung Änderungen und Erweiterungen zu einem späteren Zeitpunkt ohne größere Probleme durchzuführen.
Vorteile der MVC-Architektur
- Alle Teile sind unabhängig und austauschbar
- „Zwingt“ den Programmierer sauberen Code zu programmieren
- Erhöht die Übersichtlichkeit durch Reduzierung der Komplexität und die Kapselung der Komponeten
- Fachkräfte können optimal Ihren Fähigkeiten entsprechend eingesetzt werden
- Hoher Wert durch Wiederverwendbarkeit aller Komponenten
- Der View kann auch in Java oder z. B. in einer Shell erstellt werden, womit sich komplett neue Möglichkeiten für TYPO3 Anwendungen ergeben
Warum MVC und Typo3?
- Bereitet TYPO3 auf die konsequente Nutzung von PHP5 vor
- Löst Probleme beim Entwickeln von Extensions mit der Klasse „pi_base“
- Soll Entwicklern die TCE-Programmierung vereinfachen, da lib und div Einzug in den Core finden sollen.
- Flexibel durch "Addons" erweiterbar
- Für reine TYPO3-Programmierer ein Grund, sich mit PHP5 zu befassen
- Mit libtest wird das Testen der Anwendung vor dem eigentlichen Programmieren möglich, ähnlich wie bei PHPUnit.
- Ermöglicht große TYPO3-Extension-Projekte
- Mehr Spaß bei der Extensionentwicklung
Der Controller
Der Controller kann als dünner Adapter zwischen Ereignissen (GET/POST Parameter) auf der Webseite, welche vom View bereitgestellt wurden, und den Operationen des Models angesehen werden. Er ordnet also nur zu, welche Benutzerinteraktion (Action) welche Operationen im Model auslöst und welcher View angezeigt werden soll. Im Controller sollte keine Logik implementriert werden, er ist mehr die Intelligenz der Anwendung, also die Definition, wie der Benutzer auf die Daten des Models zugreifen kann.
Der View
Der View ist für die Präsentation der Daten verantwortlich und kennt meist seinen Controller und auch sein Model. Er kann Informationen aus dem Model abrufen und darstellen. Der View wird bei Änderungen des Models darüber informiert und gibt die Daten wieder passend aus. Eine Änderung des Views wird meist direkt vom Controller angestossen. Der View stellt die Aspekte des Zustandes eines Models dar.
Das Model
Das Model weiß nichts vom View oder dem Controller, es stellt aber Operationen bereit, die vom Controller genutzt werden können und es stellt Zustandsinformation für den View bereit – zum Beispiel den aktuellen Datensatz des eingeloggten FE-User.
Das Model repräsentiert die Zustände und Operationen der Anwendung, es enthält also die Programmlogik und den Datenzugriff, mit denen der Benutzer über den Controller agieren kann.
Beispiel: Login-Extension mit lib und div
Zum Erstellen einer Beispiel-TYPO3-Extension nach dem MVC-Konzept müssen zuerst im Extension Manager (EM) die Extensions „lib“ und „div“ installiert werden. Danach wird im Kickstarter eine neue Extension mit eventuell benötigten Tabellen angelegt. Hierbei sollte darauf geachtet werden, dass die Extension ohne Frontend-Plugins angelegt wird (FE-Plugins)! Als Extensionkey kommt hier beispielhaft „extkey“ zur Verwendung. Mit dem Speichern der Extension im Kickstarter werden nun automatisch im Ordner der neu erzeugten Extension die Ordner „controllers“, „models“, „static“, „views“ und „views/templates“ erstellt. Danach müssen die Dateien „class.tx_extkey_controllers_login.php“ (Listing 1) und „class.tx_extkey_models_feuser.php “ (Listing 2) erstellt werden:
require_once(t3lib_extMgm::extPath('div').'class.tx_div.php'); tx_div::load('tx_lib_controller'); class tx_extkey_controllers_login extends tx_lib_controller{ var $extKey = 'extkey'; var $defaultAction = 'login';//wenn keine Action function loginAction($out, $conf, $parameters){ $view = tx_div::makeInstance('tx_lib_phpView'); $view->setConfiguration($conf);//Plugin TS, Setup $view->setParameters($parameters);//GET,-POST Parameter $view->setTemplatePath($this->extPath(). 'views/templates/login/'); $model = tx_div::makeInstance('tx_extkey_models_feuser'); return $view->render($model->status());//Ausgabe }
Listing 1
Der Beispiel Controller kommt in den Order „controllers“.Dieser gibt einfach nur je nach Loginstatus des Users ein View zurück.
require_once(t3lib_extMgm::extPath('div').'class.tx_div.php'); tx_div::load('tx_lib_data'); class tx_extkey_models_feuser extends tx_lib_data{ if($GLOBALS['TSFE']->fe_user->user['username'])) return 'logout'; else return 'login', } }
Listing 2
Alle Modelle sind im Ordner „models“ azulegen. Hier, der Kürze wegen, greifen wir auf die TSFE zurück, um den Loginstatus des Users zu erhalten.
<?php if (!defined ('TYPO3_MODE'))die ('Access denied.'); $conf=$this->getConfiguration(); ?> <form class="tx_extkey_login method="post" action="" > <input type="hidden" name="logintype" value="login" /> <label for="user">Username:</label><input type="text" name="user" class="inputtext" /> <label for="password">Password:</label><input type="password" name="pass" class="inputtext" /> <input type="hidden" name="<?php echo $conf['userFolder']; ?>" /> <input type="submit" class="buttom" name="senden" value="OK" /> </form>
Listing 3
Der Logout-View im Ordner „views/templates“ gibt ein Login Form zurück. Im Moment steht ein phpView als simple Template-Engine zur Verfügung
Extensions als FE-Plugin konfigurieren
Im Ordner „static“ müssen nun noch die Dateien „setup.txt“ und „constants.txt“ erstellt werden. In diesen beiden Dateien wird der Name des Plugins definiert und der Controller zugeordnet. Hier können auch zusätzliche TypoScript-Parameter und Stylesheets übergeben werden. Um den Controller als FE-Plugin zu registrieren, muss in der Datei „ext_tables.php“ mittels der Funktion „t3lib_extMgm::addPlugin()“ aktiviert werden. Ebenfalls in der ext_tables.php mit t3lib_extMgm::addStaticFile() das Typoscript für das Root Template übergeben. Ab jetzt könnte man das neu erstellte „MVC-Plugin“ bereit auf einer TYPO3-Seite einfügen. Im Extension Manager muss die Extension allerdings noch mit einem Klick auf das „Plus-Symbol“ installiert und im Template der Hauptseite (Root-Template) das Static-TypoScript unter „Include static (from extensions)“ mit für die Seite verfügbar gemacht werden. Nach der Einbindung des neuen Plugins auf einer beliebigen TYPO3-Seite steht diese nun im Frontend zur Verfügung.
tt_content.list.20.extkey_login=< plugin.tx_extkey_login plugin.tx_extkey_login.userFolder={$plugin.tx_extkey.userFolder} plugin.tx_extkey login = USER_INT plugin.tx_extkey_login.includeLibs = EXT:extkey/controllers/class.tx_extkey_controllers_login.php plugin.tx_extkey_login._CSS_DEFAULT_STYLE ( )
Listing 4
Hiermit definieren wir unseren Controller und können Stylesheets und optionales Typoscript definieren.Wichtig ist, dass wir das Plugin als USER_INT deklarieren.
//wo soll unser login nach Usern suchen plugin.tx_extkey.userFolder = 204
Listing 5
Hier werden Constanten definiert. Hier wird die PID für den Ordner, in dem die FE-USER liegen, definiert.
t3lib_div::loadTCA('tt_content'); t3lib_extMgm::addPlugin(Array('LLL:EXT:extkey/locallang_db.php:loginPluginLabel','extkey_login'),'list_type'); t3lib_extMgm::addStaticFile('extkey','static','MVC TS');
Listing 6
Controller wird als FE-Plugin registriert und Typoscript übergeben. Hier nicht vergessen, in der locallang_db.php das Label einzufügen bzw. diese zu erstellen, wenn keine Tabellen benötigt wurden. Ebenso mit der Datei „ext_tables.php“.
Wie nun weiter?
Um nun selbst TYPO3-Extensions nach dem MVC-Prinzip zu programmieren, sollte man als erstes die Quellcodes von „lib“ und „div“ studieren. Des Weiteren gibt es auch eine Demo-Extension mit Namen „articles“, welche das MVC-Konzept beispielhaft darlegt. Sehr zu empfehlen, da bisher die einzige Dokumentation, ist das Buch „TYPO3 4.0 Handbuch für Entwickler“ von Galileo Computing [2]. Hier werden detailliert die Klassen erklärt und am Beispiel von „articles“ einige Extensions Schritt für Schritt erstellt. Auch die Newsgroup des Extension-Coordination-Teams [3] steht für Fragen oder Ideen zum Thema jedem Interessierten TYPO3-Entwickler offen. „Lib“ und „div“ sind zwar im Moment noch sehr schmal im Funktionsumfang gehalten, aber es lohnt sich schon jetzt damit zu arbeiten. Ein weiterer wichtiger Faktor ist „libtest“, welche zusammen mit „lib/div“ arbeitet und ähnlich wie PHPUnit das Konzept verfolgt, zuerst Tests für Funktionen zu schreiben, um darauf aufbauen, die eigentliche Funktionalität zu implementieren. Eine Beta Version von „lib“ und „div“ soll Anfang nächstes Jahr erscheinen und Mehrsprachigkeit, Flexforms sowie weitere TemplateEngines beinhalten. Der Entwicklung eigener Extensions nach dem MVC-Konzept sollte somit auf langfristige Sicht nichts mehr im Wege stehen.