Zend_Amf_ServerZend_Amf_Server bietet einen RPC-artigen Server für die Behandlung
der Anfragen die vom Adobe Flash Player durchgeführt werden indem das AMF Protokoll
verwendet wird. Wie alle Zend Framework Serverklassen, folgt es der SoapServer API, und
bietet ein einfach zu merkendes Interface für die Erstellung von Servern.
AMF Server Grundlagen
Angenommen wir haben eine Klasse Foo mit einer Anzahl von öffentlichen
Methoden erstellt. Man kann einen AMF Server erstellen indem der folgende Code
verwendet wird:
setClass('Foo');
$response = $server->handle();
echo $response;
]]>
Alternativ kann stattdessen man eine einfache Funktion als Callback anhängen:
addFunction('myUberCoolFunction');
$response = $server->handle();
echo $response;
]]>
Man kann auch mehrere Klassen und Funktionen mischen und verwenden. Wenn man das macht
wird empfohlen das jede von Ihnen einen Namespace erhält um sicherzustellen das keine
Kollision von Methodennamen stattfindet; das kann durchgeführt werden indem man einfach
ein zweites Stringargument entweder an addFunction() oder an
setClass() übergibt:
addFunction('myUberCoolFunction', 'my')
->setClass('Foo', 'foo')
->setClass('Bar', 'bar');
$response = $server->handle();
echo $response;
]]>Zend Amf Server erlaubt es auch Services das Sie dynamisch geladen werden,
basierend auf dem angegebenen Verzeichnispfad. Man kann dem Server so viele
Verzeichnisse wie man will hinzufügen. Die Reihenfolge in der man die Verzeichnisse zum
Server hinzufügt ist die Reihenfolge in der die LIFO Suche auf den Verzeichnissen
durchgeführt wird um die Klasse zu finden. Das Hinzufügen von Verzeichnissen wird mit
der addDirectory() Methode durchgeführt.
addDirectory(dirname(__FILE__) .'/../services/');
$server->addDirectory(dirname(__FILE__) .'/../package/');
]]>
Wenn entfernte Services aufgerufen werden kann der Quellname einen Unterstrich (_) oder
Punkt (.) Begrenzer im Verzeichnis haben. Wenn ein Unterstrich verwendet wird werden die
Namenskonventionen der PEAR und Zend Framework Klassen verwendet. Das bedeutet das wenn
man das Sevice com_Foo_Bar aufruft wird der Server nach der Datei Bar.php
suchen, und zwar in jedem der eingefügten Pfade unter com/Foo/Bar.php. Wenn
die Punkt Notation für entfernte Services wie für com.Foo.Bar verwendet
wird, wird jedem eingefügten Pfad com/Foo/Bar.php am Ende hinzugefügt um
Bar.php automatisch zu laden.
Alle AMF Anfragen die an das Skript gesendet werden, werden dan durch den Server
behandelt, und eine AMF Antwort wird zurückgegeben.
Alle angehängten Methoden und Funktionen benötigen einen Docblock
Wie alle anderen Serverkomponenten im Zend Framework müssen die Klassenmethoden
dokumentiert werden indem PHP Docblocks verwendet werden. Mindestens muß für
jedes benötigte Argument eine Beschreibung angegeben werden sowie ein Rückgabewert.
Als Beispiel:
Andere anmerkungen können verwendet werden, werden aber ignoriert.
Zum Server von Flex aus verbinden
Zum eigenen Zend_Amf_Server von einem Flex Projekt aus zu
verbinden ist recht einfach; man muß zur Endpunkt URI des
Zend_Amf_Server Sripts zeigen.
Nehmen wir zum Beispiel an das man einen Server erstellt hat und Ihn in der
server.php Datei im Anwendungsroot platziert, und die URI deswegen
http://example.com/server.php ist. In diesem Fall würde man die
services-config.xml Datei so modifizieren das das channel endpoint URI Attribut
auf diesen Wert gesetzt ist.
Wenn man noch keine service-config.xml Datei erstellt hat kann man das tun, indem
man das Projekt im Navigator Fenster öffnet. Auf dem Projektnamen rechts-klickt und
‘properties’ auswählt. Im Fenster der Projekteigenschaften muß man in das
‘Flex Build Path’ Menü, auf den ‘Library path’ Tab und sicherstellen das die ‘rpc.swc’
Datei bei den Projektpfaden hinzugefügt ist und auf Ok drücken um das Fenster zu
schließen.
Man muß dem Compiler auch mitteilen das er die service-config.xml verwenden soll um
den Endpunkt des RemoteObjects zu finden. Um das zu tun muß das Fenster der
Projekteigenschaften nochmals durch einen rechts-klick auf das Projektverzeichnis
vom Navigator aus geöffnet und Eigenschaften ausgewählt werden. Vom Eigenschaften-Popup
muß ‘Flex Compiler’ aufgewählt und der String: -services “services-config.xml”
hinzugefügt werden. Auf Apply drücken, anschließend auf OK um die Option zu
aktualisieren. Was man jetzt getan hat, ist dem Flex Compiler zu sagen das er in der
Datei services-config.xml nach Laufzeitvariablen schauen soll die von der RemotingObject
Klasse verwendet werden.
Jetzt müssen wir Flex mitteilen welche Konfigurationsdateien der Services für die
Verbindung zu unseren entfernten Methoden zu verwenden sind. Aus diesem Grund muß eine
neue ‘services-config.xml’ Datei im Flexprojekt src Verzeichnis erstellt werden. Um das
zu tun, muß man auf den Projektfolder rechts klicken und ‘new’ ‘File’ auswählen was
ein neues Fenster öffnet. Anschließend das Projektverzeichnis auswählen und dann die
Datei ‘services-config.xml’ benennen und auf beenden drücken.
Flex hat eine neue services-config.xml erstellt und Sie geöffnet. Verwende den folgenden
Beispieltext für die services-config.xml Datei. Es muß sichergestellt werden das der
Endpunkt so aktualisiert wird das er zu dem des eigenen Testservers passt. Anschließend
sicherstellen das die Datei gespeichert wird.
*
]]>
Es gibt zwei Schlüsselpunkt im Beispiel. Erstens, aber letztes im Code, erstellen wir
einen AMF Kanal, und spezifizieren den Endpunt als die URL zu unserem
Zend_Amf_Server:
]]>
Es ist zu beachten das wir diesem Kanal einen Identifikator, "zend-endpoint", gegeben
haben. Das Beispiel erstellt ein Ziel für den Service auf zu diesen Kanal zeigt,
und fügt es auch als ID hinzu -- in diesem Zall "zend".
In unseren Flex MXML Dateien müssen wir ein RemoteObject an das Service binden. In MXML
kann das wie folgt getan werden:
]]>
Hier haben wir ein neues entferntes Objekt definiert das durch "myservice" identifiziert
an das Serviceziel "zend" gebunden ist das wir in der services-config.xml
Datei definiert haben. Dann rufen wir die Methoden auf Ihnen in unserem ActionScript
einfach durch Aufruf von "myservice.<method>" auf. Als Beispiel:
Wenn wir Namespaces aktivieren würden wir "myservice.<namespace>.<method>"
verwenden:
Für weitere Informationen über den Aufruf von Flex RemoteObject, besuchen
Sie die Adobe Flex 3 Hilfeseite.
Fehlerbehandlung
Standardmäßig werden alle Exceptions die in den angehängten Klassen oder Funktionen
geworfen werden gefangen und als AMF Fehlermeldungen zurückgegeben. Trotzdem wird der
Inhalt des ErrorMessage Objekts variieren basierend darauf ob der Server im
"Produktions" Modus ist (der Standardzustand) oder nicht.
Wenn er in Produktionsmodus ist wird nur der Exceptioncode zurückgegeben. Wenn der
Produktionsmodus ausgeschaltet wird -- etwas das nur für das Testen getan werden sollte
-- werden die meisten Exceptiondetails zurückgegeben: Die Meldung der Exception, die
Zeile, und der Backtrace werden alle angehängt.
Um den Produktionsmodus auszuschalten muß das folgende getan werden:
setProduction(false);
]]>
Um Ihn wieder einzuschalten, muß stattdessen einfach ein boolscher true Wert übergeben
werden:
setProduction(true);
]]>Der Produktionsmode sollte sparsam deaktiviert werden!
Wir empfehlen den Produktionsmode nur wärend der Entwicklung auszuschalten.
Exceptionmeldungen und Backtraces können sensitive Systeminformationen enthalten
auf die nicht von Aussenstehenden zugegriffen werden darf. Selbst wenn AMF ein
binäres Format ist, ist die Spezifikation offen, was bedeutet das jeder den
Payload potentiell deserialisieren kann.
Ein Feld bei dem man im speziellen Vorsichtig sein muß ist bei PHP Fehlern selbst.
Wenn die INI Direktive display_errors aktiviert ist, wird jeder PHP
Fehler für das aktuelle Error Reporting Level direkt in der Ausgabe dargestellt --
was den AMF Antwortpayload potentiell unterbrechen kann. Wir empfehlen die
display_errors Direktive in der Produktion auszuschalten um solche
Probleme zu verhindern.
AMF Antworten
Fallweise ist es gewünscht das Antwortobjekt leicht zu manipulieren, typischerweise um
zusätzliche Nachrichtenheader zurückzugeben. Die handle() Methode des
Servers gibt das Antwortobjekt zurück, was es erlaubt das zu tun.
Nachrichtenheader der AMF Antwort hinzufügen
In diesem Beispiel fügen wir einen 'foo' Nachrichtenheader mit dem Wert 'bar' zu der
Antwort hinzu bevor sie zurückgegeben wird.
handle();
$response->addAmfHeader(new Zend_Amf_Value_MessageHeader('foo', true, 'bar'))
echo $response;
]]>Typ Objekte
Ähnlich wie SOAP, erlaubt es AMF Objekte zwischen dem Client und dem Server zu
übergeben. Das erlaubt eine große Flexibilität und Bindung zwischen den zwei Umgebungen.
Zend_Amf bietet drei Methoden für das Mappen von ActionScript und
PHP Objekten.
Erstens kann man explizite Bindungen auf Serverlevel erstellen indem die
setClassMap() Methode verwendet wird. Das erste Argument ist der
ActionScript Klassenname, das zweite ist der Name der PHP Klasse auf die gemappt
wird:
setClassMap('ContactVO', 'Contact');
]]>
Zweitens kann die öffentliche Eigenschaft $_explicitType in der
PHP Klasse gesetzt werden, wobei der Wert die ActionScript Klasse repräsentiert
auf die gemappt wird:
Drittens, in ähnlicher Art und Weise, kann eine öffentliche Methode
getASClassName() in der PHP Klasse definiert werden; diese Methode
sollte die passende ActionScript Klasse zurückgeben:
Auch wenn wir nun den ContactVO auf dem Server erstellt have müssen wir nun seine
korrespondierende Klasse in AS3 für das Server Objekt erstellen das gemappt werden soll.
Einen Rechtsklick auf das src Verzeichnis des Flex Projekts und New -> ActionScript File
auswählen. Name der Datei ContactVO und finish drücken um die neue Datei zu sehen.
Den folgenden Code in die Datei kopieren um die Erstellung der Klasse fertigzustellen.
Die Klasse ist syntaktisch identisch zu der von PHP mit dem gleichen Namen. Die
Variablennamen sind exakt die gleichen und müssen im gleichen Fall sein um korrekt
zu arbeiten. Es gibt zwei eindeutige AS3 Metatags in dieser Klasse. Das Erste kann
gebunden werden was ein Änderungsevent wirft wenn es aktualisiert wird. Das zweite Tag
ist das RemoteClass Tag welches definiert das diese klasse ein gemapptes entferntes
Objekt haben kann, in diesem Fall mit dem Aliasnamen ContactVO. Es ist
erforderlich das dieses Tag und der Wert der in der PHP Klasse gesetzt wurde, strikt
identisch sind.
Das folgende Ergebnisevent vom Serviceaufruf wird sofort zu Flex ContactVO gecastet.
Alles das bei myContact gebunden ist, wird mit den von ContactVO zurückgegebenen
Daten aktualisiert.
Von Flash aus auf den Server verbinden
Auf den Zend_Amf_Server vom Flash Projekt aus zu verbinden ist
etwas anders als von Flex aus. Trotzdem sind die Funktionen mit
Zend_Amf_Server die gleichen wie mit Flex sobald die Verbindung
erstellt wurde. Das folgende Beispiel kann auch von einer Flex AS3 Datei aus verwendet
werden. Wir werden die selbe Zend_Amf_Server Konfiguration mit
der World Klasse unserer Verbindung wiederverwenden.
Öffne Flash CS und erstelle eine neue Flash Datei (ActionScript 3). Benenne das Dokument
ZendExample.fla und speichere das Dokument in einem Verzeichnis das wir für dieses
Beispiel verwenden werden. Erstelle eine neue AS3 Datei im selben Verzeichnis und
benenne die Datei Main.as. Öffne beide Dateien im Editor. Wir werden jetzt diese zwei
Dateien über die Document Klasse verbinden. Wähle ZendExample aus und klicke auf
"stage". Im Eigenschaftsfenster von "stage" ändere die Document Klasse auf Main. Das
verbindet die Main.as ActionScript Datei mit dem Benutzer Interface von ZendExample.fla.
Wenn die Flashdatei ZendExample ausgeführt wird, dann wird die Klasse Main.as gestartet.
Als nächstes werden wir ein ActionScript hinzufügen um den AMF Aufruf durchzuführen.
Jetzt werden wir eine Main Klasse erstellen damit wir die Daten zum Server schicken und
das Ergebnis anzeigen lassen können. Kopiere den folgenden Code in die Main.as Datei und
wird werden den Code anschauen um zu erklären was die Rolle eines jeden Elements ist.
Wir müssen zuerst zwei ActionScript Bibliotheken importieren die den Haufen an Arbeit
erledigen. Das erste ist NetConnection welches wie eine Zweiwege-Leitung, zwischen dem
Client und dem Server, funktioniert. Das zweite ist ein Responder Objekt welches die
Rückgabewerte des Servers behandelt relativ zum Erfolg oder Mißerfolg des Aufrufs.
In der Klasse benötigen wir drei Variable um NetConnection, Responder, und die Gateway
URL zu unserer Zend_Amf_Server Installation zu repräsentieren.
Im Main Contructor erstellen wir einen Responder und eine neue Verbindung zum
Zend_Amf_Server Endpunkt. Der Responder definiert zwei
unterschiedliche Methoden für die Behandlung des Servers. Der Einfachheit halber haben
wir Sie onResult und onFault benannt.
In der onComplete Funktion, welche ausgeführt wird sobald das Konstrukt fertiggestellt
wurde, senden wir die Daten zum Server. Wird benötigen eine weitere zusätzliche Zeile
die den Aufruf der Zend_Amf_Server World->hello Funktion
durchführt.
Als wir die Responder Variable erstellt haben, haben wir auch eine onResult und eine
onFault Funktion definiert die die Antwort des Servers behandeln. Wir haben diese
Funktionen für ein erfolgreiches Ergebnis der Servers hunzugefügt. Ein erfolgreicher
Eventhandler wird immer dann ausgeführt wenn die Verbindung zum Server richtig
handgehabt wird.
Die onFault Funktion wird aufgerufen wenn eine ungültige Antwort vom Server
zurückgekommen ist. Das passiert wenn auf dem Server ein Fehler stattgefunden hat, die
URL zum Server ungültig ist, der entfernte Service oder die Methode nicht existiert, und
bei jedem anderen Verbindungsrelevanten Problem.
Das ActionScripts für die Erstellung der entfernten Verbindung ist jetzt fertiggestellt.
Der Aufruf der ZendExample Datei führt jetzt die Verbindung zu Zend Amf aus.
Rückblickend haben wir die benötigten Variablen hinzugefügt um eine Verbindung zum
entfernten Server zu öffnen, definiert welche Methoden in der Anwendung verwendet werden
sollen wenn die Anwendung eine Antwort vom Server empfängt, und schlußendlich die
Anzeige der zurückgegebenen Daten über trace().