Zend_Controller-Response.xml 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15741 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.controller.response">
  5. <title>Das Response Objekt</title>
  6. <sect2 id="zend.controller.response.usage">
  7. <title>Verwendung</title>
  8. <para>
  9. Das Response Objekt ist das logische Gegenstück zum <link
  10. linkend="zend.controller.request">Request Objekt</link>. Sein Zweck ist es,
  11. Inhalte und / oder Header zu vereinigen, um sie in einem Rutsch zu versenden.
  12. Zusätzlich übergibt der Front Controller alle aufgefangenen Ausnahmen an das Response
  13. Objekt, um dem Entwickler das Verarbeiten von Ausnahmen zu ermöglichen. Dies
  14. Funktionalität kann durch Setzen von
  15. <classname>Zend_Controller_Front::throwExceptions(true)</classname> überschrieben
  16. werden.
  17. </para>
  18. <programlisting language="php"><![CDATA[
  19. $front->throwExceptions(true);
  20. ]]></programlisting>
  21. <para>
  22. Um die Ausgabe der Response, inklusiver der gesetzten Header, zu senden, verwendet man
  23. <code>sendResponse()</code>:
  24. </para>
  25. <programlisting language="php"><![CDATA[
  26. $response->sendResponse();
  27. ]]></programlisting>
  28. <note>
  29. <para>
  30. Standardmäßig ruft der Front Controller <code>sendResponse()</code> auf wenn er die
  31. Anfrage fertig bearbeitet hat; typischerweise wird es nie notwendig sein Ihn
  32. aufzurufen. Wenn man trotzdem die Antwort manipulieren will oder Sie beim Testen
  33. verwenden will, kann dieses Verhalten durch das Setzen des
  34. <code>returnResponse</code> Flags mit
  35. <classname>Zend_Controller_Front::returnResponse(true)</classname> geändert werden:
  36. </para>
  37. <programlisting language="php"><![CDATA[$front->returnResponse(true);
  38. $response = $front->dispatch();
  39. // ein bischen mehr verarbeiten, wie z.B. loggen...
  40. // und dann die Ausgabe senden:
  41. $response->sendResponse();
  42. ]]></programlisting>
  43. </note>
  44. <para>
  45. Entwickler sollten das Response Objekt in ihren Aktionscontrollern verwenden. Statt
  46. die Ausgabe direkt zu machen und Header zu versenden, sollten diese an des Response
  47. Objekt übergeben werden:
  48. </para>
  49. <programlisting language="php"><![CDATA[
  50. // Innerhalb einer Controller Aktion:
  51. // Setze einen Header
  52. $this->getResponse()
  53. ->setHeader('Content-Type', 'text/html')
  54. ->appendBody($content);
  55. ]]></programlisting>
  56. <para>
  57. Dadurch werden alle Header in einem Rutsch versendet, genau vor der Anzeige des Inhalts.
  58. </para>
  59. <note>
  60. <para>
  61. Wenn die <link linkend="zend.controller.action.viewintegration">View
  62. Integration</link> des Aktion Controllers verwendet wird muß der bearbeitete
  63. Inhalt des View Skripts im Antwort Objekt nicht gesetzt werden, da die
  64. <classname>Zend_Controller_Action::render()</classname> das standardmäßig macht.
  65. </para>
  66. </note>
  67. <para>
  68. Sollte in der Anwendung eine Ausnahme auftreten, überprüft man den
  69. <code>isException()</code> Schalter des Response Objektes und erhält die Ausnahme durch
  70. Verwendung von <code>getException()</code>. Zusätzlich kann man ein eigenes Response
  71. Objekt erstellen, dass zu einer Fehlerseite umleitet, die Nachricht der Ausnahme loggt,
  72. die Nachricht der Ausnahme schön formatiert ausgibt (für Entwicklungsumgebungen), usw.
  73. </para>
  74. <para>
  75. Man kann das Response Objekt im Anschluß an die dispatch() Methode des Front Controllers
  76. erhalten oder den Front Controller auffordern, dass Response Objekt zurückzugeben
  77. statt den Inhalt auszugeben.
  78. </para>
  79. <programlisting language="php"><![CDATA[
  80. // Erhalten nach dem Dispatch:
  81. $front->dispatch();
  82. $response = $front->getResponse();
  83. if ($response->isException()) {
  84. // log, mail, etc...
  85. }
  86. // Oder den Front Controller dispatch Prozess auffordern, es zurück zu geben
  87. $front->returnResponse(true);
  88. $response = $front->dispatch();
  89. // mach irgend was...
  90. // zum Schluß, gib die Antwort aus
  91. $response->sendResponse();
  92. ]]></programlisting>
  93. <para>
  94. Standardmäßig werden Ausnahmennachrichten nicht ausgegeben. Dieses Verhalten kann durch
  95. den Aufruf von <code>renderException()</code> überschrieben werden oder indem der
  96. Front Controller aufgefordert wird, die Exceptions durch throwExceptions() auszuwerfen,
  97. wie oben gezeigt:
  98. </para>
  99. <programlisting language="php"><![CDATA[
  100. $response->renderExceptions(true);
  101. $front->dispatch($request, $response);
  102. // oder:
  103. $front->returnResponse(true);
  104. $response = $front->dispatch();
  105. $response->renderExceptions();
  106. $response->sendResponse();
  107. // oder:
  108. $front->throwExceptions(true);
  109. $front->dispatch();
  110. ]]></programlisting>
  111. </sect2>
  112. <sect2 id="zend.controller.response.headers">
  113. <title>Header manipulieren</title>
  114. <para>
  115. Wie vorher besprochen, ist einer der Aspekte der Antwort Objekt Aufgaben das Sammeln und
  116. Abschicken der HTTP Antwort Header. Eine Vielzahl von Methoden existieren hierfür:
  117. </para>
  118. <itemizedlist>
  119. <listitem>
  120. <para>
  121. <code>canSendHeaders()</code> wird verwendet um zu ermitteln ob bereits Header
  122. gesendet wurden. Sie nimmt ein zusätzliches Flag das zeigt ob eine Ausnahme
  123. geworfen werden soll oder nicht, wenn bereits Header gesendet wurden. Das kann
  124. durch das Setzen der Eigenschaft <code>headersSentThrowsException</code> zu
  125. <constant>FALSE</constant> überschrieben werden.
  126. </para>
  127. </listitem>
  128. <listitem>
  129. <para>
  130. <code>setHeader($name, $value, $replace = false)</code> wird verwendet um einen
  131. individuellen Header zu setzen. Standardmäßig, ersetzt das keinen bereits
  132. existierenden gleichnamigen Header im Objekt; Trotzdem wird das Setzen von
  133. <varname>$replace</varname> zu true es forcieren das zu tun.
  134. </para>
  135. <para>
  136. Bevor der Header setzt wird, prüft er mit <code>canSendHeaders()</code> um zu
  137. sehen ob diese Operation zu diesem Zeitpunkt erlaubt ist, und erzwingt das eine
  138. Ausnahme geworfen wird.
  139. </para>
  140. </listitem>
  141. <listitem>
  142. <para>
  143. <code>setRedirect($url, $code = 302)</code> setzt einen HTTP Location Header für
  144. eine Umleitung. Wenn ein HTTP Status Code angegeben wurde, wird dieser Status
  145. Code verwendet.
  146. </para>
  147. <para>
  148. Intern wird <code>setHeader()</code> mit dem <varname>$replace</varname> Flag
  149. aufgerufen um sicherzustellen das nur ein solcher Header jemals gesendet wird.
  150. </para>
  151. </listitem>
  152. <listitem>
  153. <para>
  154. <code>getHeaders()</code> gibt ein Array aller Header zurück. Jedes Array
  155. Element ist ein Array mit den Schlüsseln 'name' und 'value'.
  156. </para>
  157. </listitem>
  158. <listitem>
  159. <para>
  160. <code>clearHeaders()</code> löscht alle registrierten Headern.
  161. </para>
  162. </listitem>
  163. <listitem>
  164. <para>
  165. <code>setRawHeader()</code> kann verwendet werden um Header zu setzen die keine
  166. Schlüssel/Werte Paare sind, wie einen HTTP Status Header.
  167. </para>
  168. </listitem>
  169. <listitem>
  170. <para>
  171. <code>getRawHeaders()</code> gibt jeden registrierten rohen Header zurück.
  172. </para>
  173. </listitem>
  174. <listitem>
  175. <para>
  176. <code>clearRawHeaders()</code> löscht jeden registrierten rohen Header.
  177. </para>
  178. </listitem>
  179. <listitem>
  180. <para>
  181. <code>clearAllHeaders()</code> löscht beide, reguläre Schlüssel/Werte Header
  182. genauso wie rohe Header.
  183. </para>
  184. </listitem>
  185. </itemizedlist>
  186. <para>
  187. Zusätzlich zu den obigen Methoden, gint es Accessors für das Setzen und Empfangen der
  188. HTTP Antwort Codes für die aktuellen Anfrage, <code>setHttpResponseCode()</code> und
  189. <code>getHttpResponseCode()</code>.
  190. </para>
  191. </sect2>
  192. <sect2 id="zend.controller.response.namedsegments">
  193. <title>Benannte Segmente</title>
  194. <para>
  195. Das Antwort Objekt unterstützt "benannte Segmente". Das erlaubt es den Inhalt des Bodys
  196. in verschiedene Segmente zu isolieren und diese Segmente zu reihen damit die Ausgabe in
  197. einer spezifizierten Reihenfolge zurückgegeben wird. Intern wird der Inhalt der Bodys in
  198. einem Array gespeichert und die verschiedenen Accessor Methoden können verwendet werden
  199. um die Plazierung und Benamung innerhalb des Arrays zu indizieren.
  200. </para>
  201. <para>
  202. Als Beispiel könnte ein <code>preDispatch()</code> Hook verwendet werden um dem Antwort
  203. Objekt einen Header hinzuzufügen, dann den Aktion Controller einen Inhalt des Bodys
  204. hinzufügen zu lassen und einen <code>postDispatch()</code> Hook einen Footer hinzufügen
  205. zu lassen:
  206. </para>
  207. <programlisting language="php"><![CDATA[
  208. // Angenommen diese Plugin Klasse ist im Front Controller registriert
  209. class MyPlugin extends Zend_Controller_Plugin_Abstract
  210. {
  211. public function preDispatch(Zend_Controller_Request_Abstract $request)
  212. {
  213. $response = $this->getResponse();
  214. $view = new Zend_View();
  215. $view->setBasePath('../views/scripts');
  216. $response->prepend('header', $view->render('header.phtml'));
  217. }
  218. public function postDispatch(Zend_Controller_Request_Abstract $request)
  219. {
  220. $response = $this->getResponse();
  221. $view = new Zend_View();
  222. $view->setBasePath('../views/scripts');
  223. $response->append('footer', $view->render('footer.phtml'));
  224. }
  225. }
  226. // Ein Beispiel Aktion Controller
  227. class MyController extends Zend_Controller_Action
  228. {
  229. public function fooAction()
  230. {
  231. $this->render();
  232. }
  233. }
  234. ]]></programlisting>
  235. <para>
  236. Im obigen Beispiel wird ein Aufruf zu <code>/my/foo</code> den endgültigen Inhalt des
  237. Bodys des Antwort Objekts mit der folgenden Struktur verursachen:
  238. </para>
  239. <programlisting language="php"><![CDATA[
  240. array(
  241. 'header' => ..., // Header Inhalt
  242. 'default' => ..., // Body Inhalt von MyController::fooAction()
  243. 'footer' => ... // Footer Inhalt
  244. );
  245. ]]></programlisting>
  246. <para>
  247. Wenn das gerendert wird, wird es in der Reihenfolge gerendert in dem die Elements im
  248. Array angeordnet sind.
  249. </para>
  250. <para>
  251. Eine Vielzahl von Methoden kann verwendet werden um die benannten Segmente zu
  252. manipulieren:
  253. </para>
  254. <itemizedlist>
  255. <listitem>
  256. <para>
  257. <code>setBody()</code> und <code>appendBody()</code> erlauben das ein zweiter
  258. Wert, <varname>$name</varname>, übergeben wird der ein benanntes Segment
  259. indiziert. In jedem Fall wird, wenn das übergeben wird, das spezifizierte
  260. benannte Segment überschrieben oder es wird erstellt wenn es nicht existiert
  261. (standardmäßig dem Array hinzugefügt). Wenn kein benanntes Segment an
  262. <code>setBody()</code> übergeben wird, resetiert es den kompletten Inhalt des
  263. Body Arrays. Wenn kein benanntes Segment an appendBody() übergeben wird, wird
  264. der Inhalt dem Wert im 'default' benannten Segment hinzugefügt.
  265. </para>
  266. </listitem>
  267. <listitem>
  268. <para>
  269. <code>prepend($name, $content)</code> erstellt ein <varname>$name</varname>
  270. benanntes Segment und plaziert dieses ab Beginn des Arrays. Wenn das Segment
  271. bereits existiert, wird es vor der Operation entfernt (bzw, überschrieben und
  272. getauscht).
  273. </para>
  274. </listitem>
  275. <listitem>
  276. <para>
  277. <code>append($name, $content)</code> erstellt ein <varname>$name</varname>
  278. benanntes Segment und plaziert es am Ende des Arrays. Wenn das Segment bereits
  279. existiert, wird es vor der Operation entfernt (bzw, überschrieben und
  280. getauscht).
  281. </para>
  282. </listitem>
  283. <listitem>
  284. <para>
  285. <code>insert($name, $content, $parent = null, $before = false)</code> erstellt
  286. ein <varname>$name</varname> benanntes Segment. Wenn ein
  287. <varname>$parent</varname> Segment angegeben wurde, wird das neue Segment
  288. entweder vor oder nach diesem Segment im Array plaziert (basierend auf dem Wert
  289. von <varname>$before</varname>). Wenn das Segment bereits existiert, wird es
  290. vor der Operation entfernt (bzw, überschrieben und getauscht).
  291. </para>
  292. </listitem>
  293. <listitem>
  294. <para>
  295. <code>clearBody($name = null)</code> entfernt ein einzelnes benanntes Segment
  296. wenn ein <varname>$name</varname> angegeben wurde (andernfalls das komplette
  297. Array).
  298. </para>
  299. </listitem>
  300. <listitem>
  301. <para>
  302. <code>getBody($spec = false)</code> kann verwendet werden um ein einzelnes
  303. Array Segment zu erhalten wenn <varname>$spec</varname> der Name des
  304. benannten Segments ist. Wenn <varname>$spec</varname> false ist, gibt es einen
  305. String zurück der erstellt wird durch zusammenfügen aller benannten Segmente in
  306. Ihrer Reihenfolge. Wenn <varname>$spec</varname> true ist, gibt er das Array
  307. des Body Inhalts zurück.
  308. </para>
  309. </listitem>
  310. </itemizedlist>
  311. </sect2>
  312. <sect2 id="zend.controller.response.exceptions">
  313. <title>Auf Ausnahmen im Antwort Objekt testen</title>
  314. <para>
  315. Wie vorher beschrieben werden Ausnahmen standardmäßig wärend des Dispatchens gefangen
  316. und im Antwort Objekt registriert. Ausnahmen werden in einem Stack registriert, der es
  317. erlaubt alle Ausnahmen geworfen zu lassen -- Anwendungs Ausnahmen, Dispatch Ausnahmen,
  318. Plugin Ausnahmen, usw. Wenn man auf bestimmte Ausnahmen prüfen will oder Ausnahmen
  319. loggen will, muß man die Ausnahme API des Antwort Objekts verwenden:
  320. </para>
  321. <itemizedlist>
  322. <listitem>
  323. <para>
  324. <code>setException(Exception $e)</code> erlaubt es eine Ausnahme zu
  325. registrieren.
  326. </para>
  327. </listitem>
  328. <listitem>
  329. <para>
  330. <code>isException()</code> sagt ob eine Ausnahme bereits registriert wurde.
  331. </para>
  332. </listitem>
  333. <listitem>
  334. <para>
  335. <code>getException()</code> gibt den kompletten Ausnahme Stack zurück.
  336. </para>
  337. </listitem>
  338. <listitem>
  339. <para>
  340. <code>hasExceptionOfType($type)</code> erlaub es festzustellen ob eine Ausnahme
  341. einer speziellen Klasse im Stack vorhanden ist.
  342. </para>
  343. </listitem>
  344. <listitem>
  345. <para>
  346. <code>hasExceptionOfMessage($message)</code> erlaubt es festzustellen ob eine
  347. Ausnahme mit einer speziellen Nachricht im Stack vorhanden ist.
  348. </para>
  349. </listitem>
  350. <listitem>
  351. <para>
  352. <code>hasExceptionOfCode($code)</code> erlaubt es festzustellen ob eine Ausnahme
  353. mit einem bestimmten Code im Stack vorhanden ist.
  354. </para>
  355. </listitem>
  356. <listitem>
  357. <para>
  358. <code>getExceptionByType($type)</code> erlaubt es alle Ausnahmen einer
  359. speziellen Klasse vom Stack zu erhalten. False wird zurückgegeben wenn keine
  360. gefunden wurden, und andernfalls ein Array mit Ausnahmen.
  361. </para>
  362. </listitem>
  363. <listitem>
  364. <para>
  365. <code>getExceptionByMessage($message)</code> erlaubt es alle Ausnahmen mit einer
  366. speziellen Nachricht vom Stack zu erhalten. False wird zurückgegeben wenn keine
  367. gefunden wurden, und andernfalls ein Array mit Ausnahmen.
  368. </para>
  369. </listitem>
  370. <listitem>
  371. <para>
  372. <code>getExceptionByCode($code)</code> erlaubt es alle Ausnahmen mit einem
  373. speziellen Code vom Stack zu erhalten. False wird zurückgegeben wenn keine
  374. gefunden wurden, und andernfalls ein Array mit Ausnahmen.
  375. </para>
  376. </listitem>
  377. <listitem>
  378. <para>
  379. <code>renderExceptions($flag)</code> erlaubt es ein Flag zu setzen das anzeigt
  380. ob die Ausnahmen ausgegeben werden sollen wenn die Antwort gesendet wurde, oder
  381. nicht.
  382. </para>
  383. </listitem>
  384. </itemizedlist>
  385. </sect2>
  386. <sect2 id="zend.controller.response.subclassing">
  387. <title>Erben vom Antwort Objekt</title>
  388. <para>
  389. Der Zweck des Antwort Objekts ist es Header und Inhalte von den verschiedenen Aktionen
  390. und Plugins zu sammeln und diese an den Client zurückzugeben; zweitens sammelt es in der
  391. Reihenfolge Ihres auftretens alle Fehler (Ausnahmen), und gibt diese zurück, oder
  392. versteckt Sie vor dem Endbenutzer.
  393. </para>
  394. <para>
  395. Die Basis Antwort Klasse ist <classname>Zend_Controller_Response_Abstract</classname>,
  396. und jede erbende Klasse die erstellt wird sollte von dieser Klasse oder eine Ihrer
  397. Derivate erben. Die verschiedenen vorhandenen Methoden wurden in der vorhergehenden
  398. Sektion aufgezählt.
  399. </para>
  400. <para>
  401. Gründe um vom Antwort Objekt eine Subklasse zu erstellen beinhalten das Ändern wie eine
  402. Ausgabe zurückgegeben wird, basierend auf der Antwortumgebung (z.B., keine Header senden
  403. für CLI oder PHP-GTK Anfragen), zusätzliche Funktionalitäten um eine endgültige Ansicht
  404. zurückzugeben, basierend am Inhalt der in den benannten Segmenten gespeichert wurde,
  405. usw.
  406. </para>
  407. </sect2>
  408. </sect1>
  409. <!--
  410. vim:se ts=4 sw=4 et:
  411. -->