Объект ответа
Использование
Объект ответа представляет собой логическое продолжение к
объекту запроса. Его
назначение — сбор содержимого ответа и/или его заголовков, таким
образом, они могут возвращаться как одно целое. Кроме этого,
фронт-контроллер будет передавать любые пойманные исключения объекту
ответа, позволяя разработчику должным образом обрабатывать
исключения. Эта возможность может быть отключена установкой
Zend_Controller_Front::throwExceptions(true) :
$front->throwExceptions(true);
Для отправки выходных данных, включая заголовки, используйте
метод sendResponse() .
$response->sendResponse();
Note:
По умолчанию фронт-контроллер вызывает
sendResponse() , когда завершает обработку запроса,
и, скорее всего, вам никогда не потребуется вызывать этот метод.
Тем не менее, если вы хотите производить манипуляции с ответом
или использовать его в тестировании, то вы можете отменить
это поведение посредством установки флага
returnResponse методом
Zend_Controller_Front::returnResponse(true) :
$front->returnResponse(true);
$response = $front->dispatch();
// производим необходимые манипуляции с данными (например,
// журналирование), затем отправляем выходные данные:
$response->sendResponse();
Разработчики должны использовать объект ответа в своих контроллерах
действий. Вместо прямого вывода данных и отправки заголовков
помещайте их в объект ответа:
// Внутри контроллера действий:
// Установка заголовка
$this->getResponse()
->setHeader('Content-Type', 'text/html')
->appendBody($content);
Этим достигается то, что все заголовки будут отправлены
одновременно, непосредственно до того, как будет отображено
содержимое ответа.
Note:
Если используется
интеграция
вида, то вам не нужно сохранять результат рендеринга
скрипта вида в объект ответа, поскольку
Zend_Controller_Action::render() делает это по
умолчанию.
На тот случай, когда произошло исключение в приложении, проверяйте
флаг isException() в объекте ответа и
извлекайте исключение, используя getException() . Кроме
этого, можно создать собственные объекты ответа, которые производят
перенаправление на страницу ошибки, журналируют сообщения
исключений, должным образом оформляют сообщения исключений
для среды разработки и т.д.
Вы можете извлекать объект ответа после вызова метода dispatch()
фронт-контроллера или указать фронт-контроллеру, чтобы он возвращал
объект ответа вместо его вывода.
// Получение объекта ответа после диспетчеризации:
$front->dispatch();
$response = $front->getResponse();
if ($response->isException()) {
// Журналирование, отправка сообщений и т.д
}
// Либо метод dispatch() фронт-контроллера возвращает его
$front->returnResponse(true);
$response = $front->dispatch();
// Производим какие-либо манипуляции...
// В конце выводим ответ
$response->sendResponse();
По умолчанию сообщения исключений не отображаются. Это поведение
может быть отменено вызовом метода renderExceptions()
или включением через метод throwExceptions()
возможности генерации исключений фронт-контроллером, как показано
ниже:
$response->renderExceptions(true);
$front->dispatch($request, $response);
// или:
$front->returnResponse(true);
$response = $front->dispatch();
$response->renderExceptions();
$response->sendResponse();
// или:
$front->throwExceptions(true);
$front->dispatch();
Именованные сегменты
Объект ответа поддерживает именованные сегменты. Это позволяет
делить содержимое ответа на различные сегменты и упорядочивать эти
сегменты так, что вывод будет возвращаться в определенном порядке.
Внутри содержимое тела ответа сохраняется в массиве, и могут
использоваться различные методы-аксессоры для указания размещения и
имен в этом массиве.
Например, вы можете использовать перехватчик
preDispatch() для добавления верха страницы в
объект ответа, затем метод действия должен добавить тело
страницы, а перехватчик postDispatch() добавляет низ
страницы:
// Предполагается, что класс плагина зарегистрирован во фронт-контроллере
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'));
}
}
// Пример контроллера действий
class MyController extends Zend_Controller_Action
{
public function fooAction()
{
$this->render();
}
}
В примере выше вызов /my/foo приведет к тому, что
конечное содержимое тела объекта ответа будет иметь следующую
структуру:
'header' => ..., // содержимое верха страницы
'default' => ..., // содержимое тела страницы из MyController::fooAction()
'footer' => ... // содержимое низа страницы
);
Рендеринг производится в том порядке, в котором элементы
представлены в массиве.
Для управления именованными сегментами могут использоваться
различные методы:
-
setBody() и appendBody() позволяют
передавать второе значение, $name, обозначающее
именованный сегмент. В любом случае, если вы передаете его,
он перепишет этот именованный сегмент или создаст его, если
он не существует (по умолчанию добавляя в конец массива).
Если методу setBody() не был передан
именованный сегмент, то будет сброшен весь массив
содержимого тела. Если методу appendBody() не
было передано имя сегмента, то содержимое будет добавлено в
конец сегмента с именем 'default'.
-
prepend($name, $content) будет создавать
сегмент с именем $name и помещать его в начало
массива. Если сегмент уже существует, то он будет удален до
операции добавления (т.е. перезаписан).
-
append($name, $content) будет создавать сегмент
с именем $name и помещать его в конец массива.
Если сегмент уже существует, то он будет удален до операции
добавления.
-
insert($name, $content, $parent = null, $before = false)
будет создавать сегмент с именем $name. Если
был передано имя сегмента $parent (родитель),
то новый сегмент будет помещен до или после этого сегмента
(основываясь на значениии $before) в массиве.
Если сегмент уже существует, то он будет удален до операции
добавления.
-
clearBody($name = null) удалит один
сегмент, если был передано его имя $name,
иначе будет удален весь массив.
-
getBody($spec = false) может использоваться для
получения массива сегментов, если $spec - имя
именованного сегмента. Если равен false, то будет возвращена
строка, сформированная посредством объединения всех
сегментов в порядке следования. Если $spec
равен true, то он вернет массив содержимого тела.
Проверка на исключения в объекте ответа
Как было отмечено ранее, по умолчанию исключения, пойманные во время
диспетчеризации, регистрируются в объекте ответа. Исключения
регистрируются в стеке, что позволяет вам хранить все брошенные
исключения - исключения приложения, диспетчера, плагинов и т.д.
Если нужно производить проверку на определенные исключения или
журналировать их, то используйте следующее API объекта ответа для
исключений:
-
setException(Exception $e) позволяет
произвести регистрацию исключения.
-
isException() позволяет определить, было ли
зарегистрировано какое-либо исключение.
-
getException() возвращает весь стек
исключений.
-
hasExceptionOfType($type) позволяет определить
наличие в стеке исключения определенного класса.
-
hasExceptionOfMessage($message) позволяет
определить наличие в стеке исключения с заданным
сообщением.
-
hasExceptionOfCode($code) позволяет определить
наличие в стеке исключения с определенным кодом.
-
getExceptionByType($type) позволяет извлечь все
исключения определенного класса из стека.
Возвращает false, если не был найдено ни одно
исключение, иначе - массив исключений.
-
getExceptionByMessage($message) позволяет
извлекать все исключения с заданным сообщением из стека.
Возвращает false, если не был найдено ни одно
исключение, иначе - массив исключений.
-
getExceptionByCode($code) позволяет извлекать
все исключения с определенным кодом из стека.
Возвращает false, если не был найдено ни одно
исключение, иначе - массив исключений.
-
renderExceptions($flag) позволяет установить
флаг, указывающий, должны или нет отправляться исключения
вместе с ответом.
Создание подклассов объекта ответа
Назначением объекта ответа является сбор заголовков и содержимого из
различных действий и плагинов, и возврат их клиенту. Кроме этого, он
собирает все возникающие ошибки (исключения) для того, чтобы
обрабатывать их, возвращать или прятать от конечного пользователя.
Базовым классом ответа является
Zend_Controller_Response_Abstract, все
создаваемые вами подклассы должны наследовать от него или одного из
его потомков. Доступные методы были перечислены в предыдущих
разделах.
Цели, преследуемые при создании подклассов объекта ответа, включают
в себя изменение способа вывода, основанное на
окружении запроса (например, не отправлять заголовки для запросов
CLI или PHP-GTK), добавление функционала для возвращения конечного
вида, основанного на содержимом, сохраненном в именованном сегменте,
и т.д.
|
|