| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 17583 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.controller.response">
- <title>Das Response Objekt</title>
- <sect2 id="zend.controller.response.usage">
- <title>Verwendung</title>
- <para>
- Das Response Objekt ist das logische Gegenstück zum <link
- linkend="zend.controller.request">Request Objekt</link>. Sein Zweck ist es,
- Inhalte und / oder Header zu vereinigen, um sie in einem Rutsch zu versenden.
- Zusätzlich übergibt der Front Controller alle aufgefangenen Ausnahmen an das Response
- Objekt, um dem Entwickler das Verarbeiten von Ausnahmen zu ermöglichen. Dies
- Funktionalität kann durch Setzen von
- <methodname>Zend_Controller_Front::throwExceptions(true)</methodname> überschrieben
- werden.
- </para>
- <programlisting language="php"><![CDATA[
- $front->throwExceptions(true);
- ]]></programlisting>
- <para>
- Um die Ausgabe der Response, inklusiver der gesetzten Header, zu senden, verwendet man
- <methodname>sendResponse()</methodname>:
- </para>
- <programlisting language="php"><![CDATA[
- $response->sendResponse();
- ]]></programlisting>
- <note>
- <para>
- Standardmäßig ruft der Front Controller <methodname>sendResponse()</methodname> auf
- wenn er die Anfrage fertig bearbeitet hat; typischerweise wird es nie notwendig
- sein Ihn aufzurufen. Wenn man trotzdem die Antwort manipulieren will oder Sie beim
- Testen verwenden will, kann dieses Verhalten durch das Setzen des
- <property>returnResponse</property> Flags mit
- <methodname>Zend_Controller_Front::returnResponse(true)</methodname> geändert
- werden:
- </para>
- <programlisting language="php"><![CDATA[$front->returnResponse(true);
- $response = $front->dispatch();
- // ein bischen mehr verarbeiten, wie z.B. loggen...
- // und dann die Ausgabe senden:
- $response->sendResponse();
- ]]></programlisting>
- </note>
- <para>
- Entwickler sollten das Response Objekt in ihren Aktionscontrollern verwenden. Statt
- die Ausgabe direkt zu machen und Header zu versenden, sollten diese an des Response
- Objekt übergeben werden:
- </para>
- <programlisting language="php"><![CDATA[
- // Innerhalb einer Controller Aktion:
- // Setze einen Header
- $this->getResponse()
- ->setHeader('Content-Type', 'text/html')
- ->appendBody($content);
- ]]></programlisting>
- <para>
- Dadurch werden alle Header in einem Rutsch versendet, genau vor der Anzeige des Inhalts.
- </para>
- <note>
- <para>
- Wenn die <link linkend="zend.controller.action.viewintegration">View
- Integration</link> des Aktion Controllers verwendet wird muß der bearbeitete
- Inhalt des View Skripts im Antwort Objekt nicht gesetzt werden, da die
- <methodname>Zend_Controller_Action::render()</methodname> das standardmäßig macht.
- </para>
- </note>
- <para>
- Sollte in der Anwendung eine Ausnahme auftreten, überprüft man den
- <methodname>isException()</methodname> Schalter des Response Objektes und erhält die
- Ausnahme durch Verwendung von <methodname>getException()</methodname>. Zusätzlich kann
- man ein eigenes Response Objekt erstellen, dass zu einer Fehlerseite umleitet, die
- Nachricht der Ausnahme loggt, die Nachricht der Ausnahme schön formatiert ausgibt (für
- Entwicklungsumgebungen), usw.
- </para>
- <para>
- Man kann das Response Objekt im Anschluß an die <methodname>dispatch()</methodname>
- Methode des Front Controllers erhalten oder den Front Controller auffordern, dass
- Response Objekt zurückzugeben statt den Inhalt auszugeben.
- </para>
- <programlisting language="php"><![CDATA[
- // Erhalten nach dem Dispatch:
- $front->dispatch();
- $response = $front->getResponse();
- if ($response->isException()) {
- // log, mail, etc...
- }
- // Oder den Front Controller dispatch Prozess auffordern, es zurück zu geben
- $front->returnResponse(true);
- $response = $front->dispatch();
- // mach irgend was...
- // zum Schluß, gib die Antwort aus
- $response->sendResponse();
- ]]></programlisting>
- <para>
- Standardmäßig werden Ausnahmennachrichten nicht ausgegeben. Dieses Verhalten kann durch
- den Aufruf von <methodname>renderException()</methodname> überschrieben werden oder
- indem der Front Controller aufgefordert wird, die Exceptions durch
- <methodname>throwExceptions()</methodname> auszuwerfen, wie oben gezeigt:
- </para>
- <programlisting language="php"><![CDATA[
- $response->renderExceptions(true);
- $front->dispatch($request, $response);
- // oder:
- $front->returnResponse(true);
- $response = $front->dispatch();
- $response->renderExceptions();
- $response->sendResponse();
- // oder:
- $front->throwExceptions(true);
- $front->dispatch();
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.response.headers">
- <title>Header manipulieren</title>
- <para>
- Wie vorher besprochen, ist einer der Aspekte der Antwort Objekt Aufgaben das Sammeln und
- Abschicken der <acronym>HTTP</acronym> Antwort Header. Eine Vielzahl von Methoden
- existieren hierfür:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <methodname>canSendHeaders()</methodname> wird verwendet um zu ermitteln ob
- bereits Header gesendet wurden. Sie nimmt ein zusätzliches Flag das zeigt ob
- eine Ausnahme geworfen werden soll oder nicht, wenn bereits Header gesendet
- wurden. Das kann durch das Setzen der Eigenschaft
- <property>headersSentThrowsException</property> zu <constant>FALSE</constant>
- überschrieben werden.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>setHeader($name, $value, $replace = false)</methodname> wird
- verwendet um einen individuellen Header zu setzen. Standardmäßig, ersetzt das
- keinen bereits existierenden gleichnamigen Header im Objekt; Trotzdem wird das
- Setzen von <varname>$replace</varname> zu <constant>TRUE</constant> es forcieren
- das zu tun.
- </para>
- <para>
- Bevor der Header setzt wird, prüft er mit
- <methodname>canSendHeaders()</methodname> um zu sehen ob diese Operation zu
- diesem Zeitpunkt erlaubt ist, und erzwingt das eine Ausnahme geworfen wird.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>setRedirect($url, $code = 302)</methodname> setzt einen
- <acronym>HTTP</acronym> Location Header für eine Umleitung. Wenn ein
- <acronym>HTTP</acronym> Status Code angegeben wurde, wird dieser Status Code
- verwendet.
- </para>
- <para>
- Intern wird <methodname>setHeader()</methodname> mit dem
- <varname>$replace</varname> Flag aufgerufen um sicherzustellen das nur ein
- solcher Header jemals gesendet wird.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getHeaders()</methodname> gibt ein Array aller Header zurück. Jedes
- Array Element ist ein Array mit den Schlüsseln 'name' und 'value'.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>clearHeaders()</methodname> löscht alle registrierten Headern.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>setRawHeader()</methodname> kann verwendet werden um Header zu
- setzen die keine Schlüssel und Werte Paare sind, wie einen
- <acronym>HTTP</acronym> Status Header.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getRawHeaders()</methodname> gibt jeden registrierten rohen Header
- zurück.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>clearRawHeaders()</methodname> löscht jeden registrierten rohen
- Header.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>clearAllHeaders()</methodname> löscht beide, reguläre
- Schlüssel und Werte Header genauso wie rohe Header.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Zusätzlich zu den obigen Methoden, gint es Accessors für das Setzen und Empfangen der
- <acronym>HTTP</acronym> Antwort Codes für die aktuellen Anfrage,
- <methodname>setHttpResponseCode()</methodname> und
- <methodname>getHttpResponseCode()</methodname>.
- </para>
- </sect2>
- <sect2 id="zend.controller.response.namedsegments">
- <title>Benannte Segmente</title>
- <para>
- Das Antwort Objekt unterstützt "benannte Segmente". Das erlaubt es den Inhalt des Bodys
- in verschiedene Segmente zu isolieren und diese Segmente zu reihen damit die Ausgabe in
- einer spezifizierten Reihenfolge zurückgegeben wird. Intern wird der Inhalt der Bodys in
- einem Array gespeichert und die verschiedenen Accessor Methoden können verwendet werden
- um die Plazierung und Benamung innerhalb des Arrays zu indizieren.
- </para>
- <para>
- Als Beispiel könnte ein <methodname>preDispatch()</methodname> Hook verwendet werden um
- dem Antwort Objekt einen Header hinzuzufügen, dann den Aktion Controller einen Inhalt
- des Bodys hinzufügen zu lassen und einen <methodname>postDispatch()</methodname> Hook
- einen Footer hinzufügen zu lassen:
- </para>
- <programlisting language="php"><![CDATA[
- // Angenommen diese Plugin Klasse ist im Front Controller registriert
- class MyPlugin extends Zend_Controller_Plugin_Abstract
- {
- public function preDispatch(Zend_Controller_Request_Abstract $request)
- {
- $response = $this->getResponse();
- $view = new Zend_View();
- $view->setBasePath('../views/scripts');
- $response->prepend('header', $view->render('header.phtml'));
- }
- public function postDispatch(Zend_Controller_Request_Abstract $request)
- {
- $response = $this->getResponse();
- $view = new Zend_View();
- $view->setBasePath('../views/scripts');
- $response->append('footer', $view->render('footer.phtml'));
- }
- }
- // Ein Beispiel Aktion Controller
- class MyController extends Zend_Controller_Action
- {
- public function fooAction()
- {
- $this->render();
- }
- }
- ]]></programlisting>
- <para>
- Im obigen Beispiel wird ein Aufruf zu <filename>/my/foo</filename> den endgültigen
- Inhalt des Bodys des Antwort Objekts mit der folgenden Struktur verursachen:
- </para>
- <programlisting language="php"><![CDATA[
- array(
- 'header' => ..., // Header Inhalt
- 'default' => ..., // Body Inhalt von MyController::fooAction()
- 'footer' => ... // Footer Inhalt
- );
- ]]></programlisting>
- <para>
- Wenn das gerendert wird, wird es in der Reihenfolge gerendert in dem die Elements im
- Array angeordnet sind.
- </para>
- <para>
- Eine Vielzahl von Methoden kann verwendet werden um die benannten Segmente zu
- manipulieren:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <methodname>setBody()</methodname> und <methodname>appendBody()</methodname>
- erlauben das ein zweiter Wert, <varname>$name</varname>, übergeben wird der ein
- benanntes Segment indiziert. In jedem Fall wird, wenn das übergeben wird, das
- spezifizierte benannte Segment überschrieben oder es wird erstellt wenn es
- nicht existiert (standardmäßig dem Array hinzugefügt). Wenn kein benanntes
- Segment an <methodname>setBody()</methodname> übergeben wird, setzt es den
- kompletten Inhalt des Body Arrays zurück. Wenn kein benanntes Segment an
- <methodname>appendBody()</methodname> übergeben wird, wird der Inhalt dem Wert
- im 'default' benannten Segment hinzugefügt.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>prepend($name, $content)</methodname> erstellt ein
- <varname>$name</varname> benanntes Segment und plaziert dieses ab Beginn des
- Arrays. Wenn das Segment bereits existiert, wird es vor der Operation entfernt
- (bzw, überschrieben und getauscht).
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>append($name, $content)</methodname> erstellt ein
- <varname>$name</varname> benanntes Segment und plaziert es am Ende des Arrays.
- Wenn das Segment bereits existiert, wird es vor der Operation entfernt (bzw,
- überschrieben und getauscht).
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>insert($name, $content, $parent = null, $before =
- false)</methodname> erstellt ein <varname>$name</varname> benanntes
- Segment. Wenn ein <varname>$parent</varname> Segment angegeben wurde, wird das
- neue Segment entweder vor oder nach diesem Segment im Array plaziert (basierend
- auf dem Wert von <varname>$before</varname>). Wenn das Segment bereits
- existiert, wird es vor der Operation entfernt (bzw, überschrieben und
- getauscht).
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>clearBody($name = null)</methodname> entfernt ein einzelnes
- benanntes Segment wenn ein <varname>$name</varname> angegeben wurde
- (andernfalls das komplette Array).
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getBody($spec = false)</methodname> kann verwendet werden um ein
- einzelnes Array Segment zu erhalten wenn <varname>$spec</varname> der Name des
- benannten Segments ist. Wenn <varname>$spec</varname> <constant>FALSE</constant>
- ist, gibt es einen String zurück der erstellt wird durch zusammenfügen aller
- benannten Segmente in Ihrer Reihenfolge. Wenn <varname>$spec</varname>
- <constant>TRUE</constant> ist, gibt er das Array des Body Inhalts zurück.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.controller.response.exceptions">
- <title>Auf Ausnahmen im Antwort Objekt testen</title>
- <para>
- Wie vorher beschrieben werden Ausnahmen standardmäßig wärend des Dispatchens gefangen
- und im Antwort Objekt registriert. Ausnahmen werden in einem Stack registriert, der es
- erlaubt alle Ausnahmen geworfen zu lassen -- Anwendungs Ausnahmen, Dispatch Ausnahmen,
- Plugin Ausnahmen, usw. Wenn man auf bestimmte Ausnahmen prüfen will oder Ausnahmen
- loggen will, muß man die Ausnahme <acronym>API</acronym> des Antwort Objekts verwenden:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <methodname>setException(Exception $e)</methodname> erlaubt es eine Ausnahme zu
- registrieren.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>isException()</methodname> sagt ob eine Ausnahme bereits
- registriert wurde.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getException()</methodname> gibt den kompletten Ausnahme Stack
- zurück.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>hasExceptionOfType($type)</methodname> erlaub es festzustellen ob
- eine Ausnahme einer speziellen Klasse im Stack vorhanden ist.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>hasExceptionOfMessage($message)</methodname> erlaubt es
- festzustellen ob eine Ausnahme mit einer speziellen Nachricht im Stack
- vorhanden ist.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>hasExceptionOfCode($code)</methodname> erlaubt es festzustellen ob
- eine Ausnahme mit einem bestimmten Code im Stack vorhanden ist.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getExceptionByType($type)</methodname> erlaubt es alle Ausnahmen
- einer speziellen Klasse vom Stack zu erhalten. <constant>FALSE</constant> wird
- zurückgegeben wenn keine gefunden wurden, und andernfalls ein Array mit
- Ausnahmen.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getExceptionByMessage($message)</methodname> erlaubt es alle
- Ausnahmen mit einer speziellen Nachricht vom Stack zu erhalten.
- <constant>FALSE</constant> wird zurückgegeben wenn keine gefunden wurden, und
- andernfalls ein Array mit Ausnahmen.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getExceptionByCode($code)</methodname> erlaubt es alle Ausnahmen
- mit einem speziellen Code vom Stack zu erhalten. <constant>FALSE</constant> wird
- zurückgegeben wenn keine gefunden wurden, und andernfalls ein Array mit
- Ausnahmen.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>renderExceptions($flag)</methodname> erlaubt es ein Flag zu setzen
- das anzeigt ob die Ausnahmen ausgegeben werden sollen wenn die Antwort gesendet
- wurde, oder nicht.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.controller.response.subclassing">
- <title>Erben vom Antwort Objekt</title>
- <para>
- Der Zweck des Antwort Objekts ist es Header und Inhalte von den verschiedenen Aktionen
- und Plugins zu sammeln und diese an den Client zurückzugeben; zweitens sammelt es in der
- Reihenfolge Ihres auftretens alle Fehler (Ausnahmen), und gibt diese zurück, oder
- versteckt Sie vor dem Endbenutzer.
- </para>
- <para>
- Die Basis Antwort Klasse ist <classname>Zend_Controller_Response_Abstract</classname>,
- und jede erbende Klasse die erstellt wird sollte von dieser Klasse oder eine Ihrer
- Derivate erben. Die verschiedenen vorhandenen Methoden wurden in der vorhergehenden
- Sektion aufgezählt.
- </para>
- <para>
- Gründe um vom Antwort Objekt eine Subklasse zu erstellen beinhalten das Ändern wie eine
- Ausgabe zurückgegeben wird, basierend auf der Antwortumgebung (z.B., keine Header senden
- für <acronym>CLI</acronym> oder <acronym>PHP</acronym>-<acronym>GTK</acronym> Anfragen),
- zusätzliche Funktionalitäten um eine endgültige Ansicht zurückzugeben, basierend am
- Inhalt der in den benannten Segmenten gespeichert wurde, usw.
- </para>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|