[ZF-10089] Zend_Log
[zend.git] / documentation / manual / ru / module_specs / Zend_Controller-Response.xml
blob5ab7bd96572d28559a23fe3707bf72a4f4240598
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.controller.response">
4     <title>Объект ответа</title>
6     <sect2 id="zend.controller.response.usage">
7         <title>Использование</title>
9         <para>
10             Объект ответа представляет собой логическое продолжение к
11             <link linkend="zend.controller.request">объекту запроса</link>. Его
12             назначение — сбор содержимого ответа и/или его заголовков, таким
13             образом, они могут возвращаться как одно целое. Кроме этого,
14             фронт-контроллер будет передавать любые пойманные исключения объекту
15             ответа, позволяя разработчику должным образом обрабатывать
16             исключения. Эта возможность может быть отключена установкой
17             <code>Zend_Controller_Front::throwExceptions(true)</code>:
18         </para>
20         <programlisting language="php"><![CDATA[
21 $front->throwExceptions(true);
22 ]]></programlisting>
24         <para>
25             Для отправки выходных данных, включая заголовки, используйте
26             метод <code>sendResponse()</code>.
27         </para>
29         <programlisting language="php"><![CDATA[
30 $response->sendResponse();
31 ]]></programlisting>
33         <note>
34             <para>
35                 По умолчанию фронт-контроллер вызывает
36                 <code>sendResponse()</code>, когда завершает обработку запроса,
37                 и, скорее всего, вам никогда не потребуется вызывать этот метод.
38                 Тем не менее, если вы хотите производить манипуляции с ответом
39                 или использовать его в тестировании, то вы можете отменить
40                 это поведение посредством установки флага
41                 <code>returnResponse</code> методом
42                 <code>Zend_Controller_Front::returnResponse(true)</code>:
43             </para>
45             <programlisting language="php"><![CDATA[
46 $front->returnResponse(true);
47 $response = $front->dispatch();
49 // производим необходимые манипуляции с данными (например,
50 // журналирование), затем отправляем выходные данные:
51 $response->sendResponse();
52 ]]></programlisting>
53         </note>
55         <para>
56             Разработчики должны использовать объект ответа в своих контроллерах
57             действий. Вместо прямого вывода данных и отправки заголовков
58             помещайте их в объект ответа:
59         </para>
61         <programlisting language="php"><![CDATA[
62 // Внутри контроллера действий:
63 // Установка заголовка
64 $this->getResponse()
65     ->setHeader('Content-Type', 'text/html')
66     ->appendBody($content);
67 ]]></programlisting>
69         <para>
70             Этим достигается то, что все заголовки будут отправлены
71             одновременно, непосредственно до того, как будет отображено
72             содержимое ответа.
73         </para>
75         <note>
76             <para>
77                 Если используется
78                 <link
79                 linkend="zend.controller.action.viewintegration">интеграция
80                 вида</link>, то вам не нужно сохранять результат рендеринга
81                 скрипта вида в объект ответа, поскольку
82                 <code>Zend_Controller_Action::render()</code> делает это по
83                 умолчанию.
84             </para>
85         </note>
87         <para>
88             На тот случай, когда произошло исключение в приложении, проверяйте
89             флаг <code>isException()</code> в объекте ответа и
90             извлекайте исключение, используя <code>getException()</code>. Кроме
91             этого, можно создать собственные объекты ответа, которые производят
92             перенаправление на страницу ошибки, журналируют сообщения
93             исключений, должным образом оформляют сообщения исключений
94             для среды разработки и т.д.
95         </para>
97         <para>
98             Вы можете извлекать объект ответа после вызова метода dispatch()
99             фронт-контроллера или указать фронт-контроллеру, чтобы он возвращал
100             объект ответа вместо его вывода.
101         </para>
103         <programlisting language="php"><![CDATA[
104 // Получение объекта ответа после диспетчеризации:
105 $front->dispatch();
106 $response = $front->getResponse();
107 if ($response->isException()) {
108     // Журналирование, отправка сообщений и т.д
111 // Либо метод dispatch() фронт-контроллера возвращает его
112 $front->returnResponse(true);
113 $response = $front->dispatch();
115 // Производим какие-либо манипуляции...
117 // В конце выводим ответ
118 $response->sendResponse();
119 ]]></programlisting>
121         <para>
122             По умолчанию сообщения исключений не отображаются. Это поведение
123             может быть отменено вызовом метода <code>renderExceptions()</code>
124             или включением через метод <code>throwExceptions()</code>
125             возможности генерации исключений фронт-контроллером, как показано
126             ниже:
127         </para>
129         <programlisting language="php"><![CDATA[
130 $response->renderExceptions(true);
131 $front->dispatch($request, $response);
133 // или:
134 $front->returnResponse(true);
135 $response = $front->dispatch();
136 $response->renderExceptions();
137 $response->sendResponse();
139 // или:
140 $front->throwExceptions(true);
141 $front->dispatch();
142 ]]></programlisting>
143     </sect2>
145     <sect2 id="zend.controller.response.headers">
146         <title>Управление заголовками</title>
148         <para>
149             Как было замечено ранее, одной из обязанностей объекта ответа
150             является сбор и отправка заголовков ответа HTTP. Для этого есть
151             различные методы:
152         </para>
154         <itemizedlist>
155             <listitem>
156                 <para>
157                     <code>canSendHeaders()</code> используется  для определения
158                     того, были ли заголовки отправлены ранее. Опционально он
159                     принимает флаг, указывающий, бросать или нет исключение,
160                     если заголовки были уже отправлены. Генерация таких
161                     исключений может быть отменена посредством установки
162                     свойства <code>headersSentThrowsException</code> в
163                     <constant>FALSE</constant>.
164                 </para>
165             </listitem>
167             <listitem>
168                 <para>
169                     <code>setHeader($name, $value, $replace = false)</code>
170                     используется для установки отдельного заголовка. По
171                     умолчанию он не замещает в объекте существующие под тем же
172                     именем заголовки. Но установкой
173                     <varname>$replace</varname> в <constant>TRUE</constant> можно произвести
174                     принудительную замену заголовка.
175                 </para>
177                 <para>
178                     До установки заголовка он вызывает другой метод
179                     <code>canSendHeaders()</code> для проверки того, можно ли
180                     выполнить данную операцию, и прверяет, было ли брошено
181                     исключение.
182                 </para>
183             </listitem>
185             <listitem>
186                 <para>
187                     <code>setRedirect($url, $code = 302)</code> устанавливает
188                     HTTP-заголовок &quot;Location&quot; для перенаправления.
189                     Если был передан код статуса HTTP, то он будет
190                     использоваться при перенаправлении.
191                 </para>
193                 <para>
194                     Внутри себя он вызывает <code>setHeader()</code> со
195                     флагом <varname>$replace</varname> для обеспечения гарантии того,
196                     что отправляется только один такой заголовок.
197                 </para>
198             </listitem>
200             <listitem>
201                 <para>
202                     <code>getHeaders()</code> возвращает массив всех заголовков.
203                     Каждый элемент массива является массивом со ключами 'name' и
204                     'value'.
205                 </para>
206             </listitem>
208             <listitem>
209                 <para>
210                     <code>clearHeaders()</code> удаляет все зарегистрированные
211                     ранее заголовки.
212                 </para>
213             </listitem>
215             <listitem>
216                 <para>
217                     <code>setRawHeader()</code> может использоваться для
218                     установки заголовков, которые не являются парами
219                     ключ/значение, например, заголовок статуса HTTP.
220                 </para>
221             </listitem>
223             <listitem>
224                 <para>
225                     <code>getRawHeaders()</code> возвращает все
226                     зарегистрированные через <code>setRawHeader()</code>
227                     заголовки.
228                 </para>
229             </listitem>
231             <listitem>
232                 <para>
233                     <code>clearRawHeaders()</code> удаляет все
234                     зарегистрированные через <code>setRawHeader()</code>
235                     заголовки.
236                 </para>
237             </listitem>
239             <listitem>
240                 <para>
241                     <code>clearAllHeaders()</code> удаляет как обычные
242                     заголовки из пар ключ/значение, так и
243                     &quot;необработанные&quot; (raw).
244                 </para>
245             </listitem>
246         </itemizedlist>
248         <para>
249             Кроме перечисленных выше методов, есть аксессоры для установки и
250             получения кода ответа для текущего запроса,
251             <code>setHttpResponseCode()</code> и
252             <code>getHttpResponseCode()</code>.
253         </para>
254     </sect2>
256     <sect2 id="zend.controller.response.namedsegments">
257         <title>Именованные сегменты</title>
259         <para>
260             Объект ответа поддерживает именованные сегменты. Это позволяет
261             делить содержимое ответа на различные сегменты и упорядочивать эти
262             сегменты так, что вывод будет возвращаться в определенном порядке.
263             Внутри содержимое тела ответа сохраняется в массиве, и могут
264             использоваться различные методы-аксессоры для указания размещения и
265             имен в этом массиве.
266         </para>
268         <para>
269             Например, вы можете использовать перехватчик
270             <code>preDispatch()</code> для добавления верха страницы в
271             объект ответа, затем метод действия должен добавить тело
272             страницы, а перехватчик <code>postDispatch()</code> добавляет низ
273             страницы:
274         </para>
276         <programlisting language="php"><![CDATA[
277 // Предполагается, что класс плагина зарегистрирован во фронт-контроллере
278 class MyPlugin extends Zend_Controller_Plugin_Abstract
280     public function preDispatch(Zend_Controller_Request_Abstract $request)
281     {
282         $response = $this->getResponse();
283         $view = new Zend_View();
284         $view->setBasePath('../views/scripts');
286         $response->prepend('header', $view->render('header.phtml'));
287     }
289     public function postDispatch(Zend_Controller_Request_Abstract $request)
290     {
291         $response = $this->getResponse();
292         $view = new Zend_View();
293         $view->setBasePath('../views/scripts');
295         $response->append('footer', $view->render('footer.phtml'));
296     }
299 // Пример контроллера действий
300 class MyController extends Zend_Controller_Action
302     public function fooAction()
303     {
304         $this->render();
305     }
307 ]]></programlisting>
309         <para>
310             В примере выше вызов <code>/my/foo</code> приведет к тому, что
311             конечное содержимое тела объекта ответа будет иметь следующую
312             структуру:
313         </para>
315         <programlisting language="php"><![CDATA[
316 array(
317     'header'  => ..., // содержимое верха страницы
318     'default' => ..., // содержимое тела страницы из MyController::fooAction()
319     'footer'  => ...  // содержимое низа страницы
321 ]]></programlisting>
323         <para>
324             Рендеринг производится в том порядке, в котором элементы
325             представлены в массиве.
326         </para>
328         <para>
329             Для управления именованными сегментами могут использоваться
330             различные методы:
331         </para>
333         <itemizedlist>
334             <listitem>
335                 <para>
336                     <code>setBody()</code> и <code>appendBody()</code> позволяют
337                     передавать второе значение, <varname>$name</varname>, обозначающее
338                     именованный сегмент. В любом случае, если вы передаете его,
339                     он перепишет этот именованный сегмент или создаст его, если
340                     он не существует (по умолчанию добавляя в конец массива).
341                     Если методу <code>setBody()</code> не был передан
342                     именованный сегмент, то будет сброшен весь массив
343                     содержимого тела. Если методу <code>appendBody()</code> не
344                     было передано имя сегмента, то содержимое будет добавлено в
345                     конец сегмента с именем 'default'.
346                 </para>
347             </listitem>
349             <listitem>
350                 <para>
351                     <code>prepend($name, $content)</code> будет создавать
352                     сегмент с именем <varname>$name</varname> и помещать его в начало
353                     массива. Если сегмент уже существует, то он будет удален до
354                     операции добавления (т.е. перезаписан).
355                 </para>
356             </listitem>
358             <listitem>
359                 <para>
360                     <code>append($name, $content)</code> будет создавать сегмент
361                     с именем <varname>$name</varname> и помещать его в конец массива.
362                     Если сегмент уже существует, то он будет удален до операции
363                     добавления.
364                 </para>
365             </listitem>
367             <listitem>
368                 <para>
369                     <code>insert($name, $content, $parent = null, $before = false)</code>
370                     будет создавать сегмент с именем <varname>$name</varname>. Если
371                     был передано имя сегмента <varname>$parent</varname> (родитель),
372                     то новый сегмент будет помещен до или после этого сегмента
373                     (основываясь на значениии <varname>$before</varname>) в массиве.
374                     Если сегмент уже существует, то он будет удален до операции
375                     добавления.
376                 </para>
377             </listitem>
379             <listitem>
380                 <para>
381                     <code>clearBody($name = null)</code> удалит один
382                     сегмент, если был передано его имя <varname>$name</varname>,
383                     иначе будет удален весь массив.
384                 </para>
385             </listitem>
387             <listitem>
388                 <para>
389                     <code>getBody($spec = false)</code> может использоваться для
390                     получения массива сегментов, если <varname>$spec</varname> - имя
391                     именованного сегмента. Если равен false, то будет возвращена
392                     строка, сформированная посредством объединения всех
393                     сегментов в порядке следования. Если <varname>$spec</varname>
394                     равен true, то он вернет массив содержимого тела.
395                 </para>
396             </listitem>
397         </itemizedlist>
398     </sect2>
400     <sect2 id="zend.controller.response.exceptions">
401         <title>Проверка на исключения в объекте ответа</title>
403         <para>
404             Как было отмечено ранее, по умолчанию исключения, пойманные во время
405             диспетчеризации, регистрируются в объекте ответа. Исключения
406             регистрируются в стеке, что позволяет вам хранить все брошенные
407             исключения - исключения приложения, диспетчера, плагинов и т.д.
408             Если нужно производить проверку на определенные исключения или
409             журналировать их, то используйте следующее API объекта ответа для
410             исключений:
411         </para>
413         <itemizedlist>
414             <listitem>
415                 <para>
416                     <code>setException(Exception $e)</code> позволяет
417                     произвести регистрацию исключения.
418                 </para>
419             </listitem>
421             <listitem>
422                 <para>
423                     <code>isException()</code> позволяет определить, было ли
424                     зарегистрировано какое-либо исключение.
425                 </para>
426             </listitem>
428             <listitem>
429                 <para>
430                     <code>getException()</code> возвращает весь стек
431                     исключений.
432                 </para>
433             </listitem>
435             <listitem>
436                 <para>
437                     <code>hasExceptionOfType($type)</code> позволяет определить
438                     наличие в стеке исключения определенного класса.
439                 </para>
440             </listitem>
442             <listitem>
443                 <para>
444                     <code>hasExceptionOfMessage($message)</code> позволяет
445                     определить наличие в стеке исключения с заданным
446                     сообщением.
447                 </para>
448             </listitem>
450             <listitem>
451                 <para>
452                     <code>hasExceptionOfCode($code)</code> позволяет определить
453                     наличие в стеке исключения с определенным кодом.
454                 </para>
455             </listitem>
457             <listitem>
458                 <para>
459                     <code>getExceptionByType($type)</code> позволяет извлечь все
460                     исключения определенного класса из стека.
461                     Возвращает false, если не был найдено ни одно
462                     исключение, иначе - массив исключений.
463                 </para>
464             </listitem>
466             <listitem>
467                 <para>
468                     <code>getExceptionByMessage($message)</code> позволяет
469                     извлекать все исключения с заданным сообщением из стека.
470                     Возвращает false, если не был найдено ни одно
471                     исключение, иначе - массив исключений.
472                 </para>
473             </listitem>
475             <listitem>
476                 <para>
477                     <code>getExceptionByCode($code)</code> позволяет извлекать
478                     все исключения с определенным кодом из стека.
479                     Возвращает false, если не был найдено ни одно
480                     исключение, иначе - массив исключений.
481                 </para>
482             </listitem>
484             <listitem>
485                 <para>
486                     <code>renderExceptions($flag)</code> позволяет установить
487                     флаг, указывающий, должны или нет отправляться исключения
488                     вместе с ответом.
489                 </para>
490             </listitem>
491         </itemizedlist>
492     </sect2>
494     <sect2 id="zend.controller.response.subclassing">
495         <title>Создание подклассов объекта ответа</title>
497         <para>
498             Назначением объекта ответа является сбор заголовков и содержимого из
499             различных действий и плагинов, и возврат их клиенту. Кроме этого, он
500             собирает все возникающие ошибки (исключения) для того, чтобы
501             обрабатывать их, возвращать или прятать от конечного пользователя.
502         </para>
504         <para>
505             Базовым классом ответа является
506             <classname>Zend_Controller_Response_Abstract</classname>, все
507             создаваемые вами подклассы должны наследовать от него или одного из
508             его потомков. Доступные методы были перечислены в предыдущих
509             разделах.
510         </para>
512         <para>
513             Цели, преследуемые при создании подклассов объекта ответа, включают
514             в себя изменение способа вывода, основанное на
515             окружении запроса (например, не отправлять заголовки для запросов
516             CLI или PHP-GTK), добавление функционала для возвращения конечного
517             вида, основанного на содержимом, сохраненном в именованном сегменте,
518             и т.д.
519         </para>
520     </sect2>
521 </sect1>
522 <!--
523 vim:se ts=4 sw=4 et: