Biphrost: Transfer
Die eigentliche Aufgabe der
Transfer-Komponente besteht im Transport von Daten zwischen
verschiedenen Schichten, weshalb die die Transfer-Klasse das Data-Transfer-Object-Entwurfsmuster
implementiert. Ein wesentlicher Aspekt dieses Entwurfsmusters ist das
Fehlen jeglicher Funktionalität, wenn man vom Zugriff und dem Halten
der Daten absieht.
Nebeneffekt dieses Konzepts ist das Vermeiden von globalen
Abhängigkeiten und eine transparente Wiederverwendung eines
Transfer-Objekts.
Ein Transfer-Objekt kann verschiedene Daten beinhalten:
- Argumente, also nicht verbrauchte Komponenten des URIs. (siehe: Einstiegspunkte)
- Daten der Außenwelt (Sessions, Cookies, GET-, POST- und SERVER-Variablen)
- Flag, das angibt, ob das Transfer-Objekt abgefertigt wurde
- Applikationsdaten
Für den Zugriff auf die Daten der ersten drei Typen werden Methoden bereitgestellt:
- Lesen eines einzelnen Werts: argument, cookie, get, post, server, session, wasDispatched
- Lesen aller Werte: getArguments, getCookies, getGet, getPost, getServer, getSession.
- Schreiben aller Werte: setArguments, setCookies, setGet, setPost, setServer, setSession.
- Schreiben eines einzelnen Werts ist nur bei der Session (setSessionVar) und dem Abfertigungsflag (dispatch) möglich.
Da die o.g. Argumente normalerweise nicht mit Namen assoziiert sind, existiert eine Methode um diesen Missstand zu beheben: nameArguments.
$transfer->getArguments(); // array('12', '34')
$transfer->argument(0); // '12'
$transfer->nameArguments(array('foo', 'bar'));
$transfer->getArguments(); // array('12', '34', 'foo' => '12', 'bar' => '34')
$transfer->argument('foo'); // '12'
Mit dieser Methode lässt sich der Code viel klarer ausdrücken, da man der Methode argument nun einen String übergeben kann statt eines Zahlenwerts.
Ein besonderer Status kommt den Applikationsdaten zu, die beliebig an
das Transfer-Objekt gehängt werden können. Durch die Einführung solcher
Daten ist es möglich, Initialisierungen vorzunehmen und die Applikation
auszuwerten. So ist es üblich, dass ein Template, das am Ende
dargestellt werden soll, im Einstiegspunkt an das Transfer-Objekt
angehängt wird. Erreicht das Transfer-Objekt nun das Ende des
Abfertigungsprozesses, kann das Template dargestellt werden. Am Anfang
dieses Prozesses hingegen könnte man eine Datenbank initialisieren und
dem Transfer-Objekt mitgeben. Dadurch kann man globale Abhängigkeiten
auflösen, da man Daten lokal an das Transfer-Objekt übergeben kann und
nicht mehr auf die Existenz eines globalen Zugriffspunkts angewiesen
ist, z.B. auf einen Singleton für den Zugriff auf eine Datenbankinstanz. Um dieses Verhalten zu propagieren wurden die magischen Methoden __get, __set, __unset und __isset genutzt, damit sich der Umgang intuitiver wird. Neben diesem Zugriff kann man die Applikationsdaten mit den Methoden setVariables und getVariables setzen bzw. zurückgeben lassen.
Am Transfer-Objekt werden an verschiedenen Stellen Änderungen vorgenommen:
- Das Setzen von Daten der Außenwelt in der Bootstrap-Datei.
- Applikationsdaten werden in einer Unterklasse von "Application" gesetzt.
- Die unbenannten Argumente werden vom Dispatcher eingefügt.
An den beiden letztgenannten Punkten wird das Transfer-Objekt lediglich als Prototyp benutzt und die Änderungen an einem neuen Objekt vorgenommen. Dieses Vorgehen ermöglicht die Wiederverwendung eines Transfer-Objekts, da Änderungen in einem Abfertigungsprozess nicht auf den ursprünglichen Prototypen übernommen werden, womit sich in einem Einstiegspunkt ein weiterer Einstiegspunkt transparent abfertigen lässt.