Spec-Zone.ru › Yii 2.0

Ответы

  1. Код состояния
  2. HTTP-заголовки
  3. Тело ответа
  4. Перенаправление браузера
  5. Отправка файлов
  6. Отправка ответа

Когда приложение завершает обработку запроса, оно генерирует объект ответа и отправляет его конечному пользователю. Объект ответа содержит информацию, такую как код состояния HTTP, HTTP-заголовки и тело. Конечная цель разработки веб-приложений — в конечном счёте создавать такие объекты ответа на различные запросы.

В большинстве случаев вам нужно будет работать в основном с response компонентом приложения, который по умолчанию является экземпляром yii\web\Response. Однако Yii также позволяет вам создавать собственные объекты ответа и отправлять их конечным пользователям, как мы объясним далее.

В этом разделе мы опишем, как составлять и отправлять ответы конечным пользователям.

Код состояния

Одним из первых действий при создании ответа будет указание того, был ли запрос успешно обработан. Это делается путём установки свойства yii\web\Response::$statusCode, которое может принимать одно из допустимых значений кодов состояния HTTP. Например, чтобы указать, что запрос был успешно обработан, вы можете установить код состояния в 200, как показано ниже:

Yii::$app->response->statusCode = 200;

Однако в большинстве случаев вам не нужно явно устанавливать код состояния. Это связано с тем, что значение по умолчанию для yii\web\Response::$statusCode равно 200. А если вы хотите указать, что запрос был неуспешным, вы можете бросить соответствующее исключение HTTP, как показано ниже:

throw new \yii\web\NotFoundHttpException;

Когда обработчик ошибок перехватывает исключение, он извлекает код состояния из исключения и присваивает его ответу. Для yii\web\NotFoundHttpException выше, он связан с кодом состояния HTTP 404. В Yii определены следующие исключения HTTP:

  • yii\web\BadRequestHttpException: код состояния 400.
  • yii\web\ConflictHttpException: код состояния 409.
  • yii\web\ForbiddenHttpException: код состояния 403.
  • yii\web\GoneHttpException: код состояния 410.
  • yii\web\MethodNotAllowedHttpException: код состояния 405.
  • yii\web\NotAcceptableHttpException: код состояния 406.
  • yii\web\NotFoundHttpException: код состояния 404.
  • yii\web\ServerErrorHttpException: код состояния 500.
  • yii\web\TooManyRequestsHttpException: код состояния 429.
  • yii\web\UnauthorizedHttpException: код состояния 401.
  • yii\web\UnsupportedMediaTypeHttpException: код состояния 415.

Если исключение, которое вы хотите бросить, не находится в этом списке, вы можете создать его, расширив класс yii\web\HttpException, или непосредственно бросить его с кодом состояния, например,

throw new \yii\web\HttpException(402);

HTTP-заголовки

Вы можете отправлять HTTP-заголовки, манипулируя коллекцией заголовков в компоненте response. Например,

$headers = Yii::$app->response->headers;

// add a Pragma header. Existing Pragma headers will NOT be overwritten.
$headers->add('Pragma', 'no-cache');

// set a Pragma header. Any existing Pragma headers will be discarded.
$headers->set('Pragma', 'no-cache');

// remove Pragma header(s) and return the removed Pragma header values in an array
$values = $headers->remove('Pragma');

Примечание: Имена заголовков нечувствительны к регистру. А новые зарегистрированные заголовки не отправляются пользователю до тех пор, пока не будет вызван метод yii\web\Response::send().

Тело ответа

Большинство ответов должны иметь тело, которое содержит контент, который вы хотите отобразить конечным пользователям.

Если у вас уже есть отформатированная строка тела, вы можете присвоить её свойству yii\web\Response::$content ответа. Например,

Yii::$app->response->content = 'hello world!';

Если ваши данные необходимо отформатировать перед отправкой конечным пользователям, вы должны установить свойства формата и данных. Свойство формата указывает, в каком формате должны быть отформатированы данные данных. Например,

$response = Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON;
$response->data = ['message' => 'hello world'];

Yii поддерживает следующие форматы «из коробки», каждый из которых реализован классом форматера. Вы можете настроить эти форматеры или добавить новые, настроив свойство yii\web\Response::$formatters.

  • HTML: реализован классом yii\web\HtmlResponseFormatter.
  • XML: реализован классом yii\web\XmlResponseFormatter.
  • JSON: реализован классом yii\web\JsonResponseFormatter.
  • JSONP: реализован классом yii\web\JsonResponseFormatter.
  • RAW: используйте этот формат, если хотите отправить ответ напрямую без применения форматирования.

Хотя тело ответа можно установить явно, как показано выше, в большинстве случаев вы можете установить его неявно, используя значение возвращаемого результата методов действий. Типичный пример использования выглядит следующим образом:

public function actionIndex()
{
    return $this->render('index');
}

Действие index выше возвращает результат рендеринга представления index. Возвращаемое значение будет взято компонентом response, отформатировано и отправлено конечным пользователям.

Поскольку по умолчанию формат ответа — HTML, вы должны возвращать только строку в методе действия. Если вы хотите использовать другой формат ответа, вам необходимо его установить перед возвратом данных. Например,

public function actionInfo()
{
    \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    return [
        'message' => 'hello world',
        'code' => 100,
    ];
}

Как уже упоминалось, помимо использования компонента приложения response по умолчанию, вы также можете создавать свои собственные объекты ответа и отправлять их конечным пользователям. Вы можете сделать это, вернув такой объект в методе действия, как показано ниже,

public function actionInfo()
{
    return \Yii::createObject([
        'class' => 'yii\web\Response',
        'format' => \yii\web\Response::FORMAT_JSON,
        'data' => [
            'message' => 'hello world',
            'code' => 100,
        ],
    ]);
}

Примечание: Если вы создаёте собственные объекты ответа, вы не сможете воспользоваться настройками, которые вы установили для компонента response в конфигурации приложения. Однако вы можете использовать инъекцию зависимостей, чтобы применить общую конфигурацию к вашим новым объектам ответа.

Перенаправление браузера

Перенаправление браузера основано на отправке заголовка Location HTTP. Поскольку эта функция часто используется, Yii предоставляет для неё особую поддержку.

Вы можете перенаправить браузер пользователя на URL, вызвав метод yii\web\Response::redirect(). Метод устанавливает соответствующий заголовок Location с заданным URL и возвращает сам объект ответа. В методе действия вы можете вызвать его сокращённую версию yii\web\Controller::redirect(). Например,

public function actionOld()
{
    return $this->redirect('http://example.com/new', 301);
}

В коде выше метод действия возвращает результат метода redirect(). Как объяснялось ранее, объект ответа, возвращённый методом действия, будет использован в качестве ответа, отправляемого конечным пользователям.

В местах, отличных от метода действия, вы должны напрямую вызвать yii\web\Response::redirect(), после чего вызвать цепочку вызовов метода yii\web\Response::send(), чтобы убедиться, что к ответу не будет добавлено дополнительного контента.

\Yii::$app->response->redirect('http://example.com/new', 301)->send();

Примечание: По умолчанию метод yii\web\Response::redirect() устанавливает код состояния ответа в 302, что сообщает браузеру, что запрашиваемый ресурс временно находится по другому URI. Вы можете передать код состояния 301, чтобы сообщить браузеру, что ресурс был навсегда перемещён.

Если текущий запрос является AJAX-запросом, отправка заголовка Location не заставит браузер автоматически перенаправляться. Чтобы решить эту проблему, метод yii\web\Response::redirect() устанавливает заголовок X-Redirect со значением URL перенаправления. В коде клиента вы можете написать код JavaScript, чтобы прочитать значение этого заголовка и перенаправить браузер соответственно.

Примечание: Yii поставляется с файлом JavaScript yii.js , который предоставляет набор часто используемых утилит JavaScript, включая перенаправление браузера на основе заголовка X-Redirect. Поэтому, если вы используете этот файл JavaScript (зарегистрировав пакет ресурсов yii\web\YiiAsset), вам не нужно ничего писать, чтобы поддерживать AJAX-перенаправление. Более подробную информацию о yii.js можно найти в разделе Клиентские скрипты.

Отправка файлов

Подобно перенаправлению браузера, отправка файлов — это ещё одна функция, которая основана на определённых HTTP-заголовках. Yii предоставляет набор методов для поддержки различных потребностей в отправке файлов. Они все включают встроенную поддержку заголовка HTTP range.

  • yii\web\Response::sendFile(): отправляет существующий файл клиенту.
  • yii\web\Response::sendContentAsFile(): отправляет строку текста как файл клиенту.
  • yii\web\Response::sendStreamAsFile(): отправляет существующий поток файла как файл клиенту.

Эти методы имеют ту же сигнатуру метода с возвращаемым объектом ответа. Если файл, который нужно отправить, очень большой, вы должны рассмотреть использование yii\web\Response::sendStreamAsFile(), так как он более эффективен с точки зрения использования памяти. Следующий пример показывает, как отправить файл в действии контроллера:

public function actionDownload()
{
    return \Yii::$app->response->sendFile('path/to/file.txt');
}

Если вы вызываете метод отправки файла в местах, отличных от метода действия, вы также должны вызвать метод yii\web\Response::send() после него, чтобы убедиться, что к ответу не будет добавлено дополнительного контента.

\Yii::$app->response->sendFile('path/to/file.txt')->send();

Некоторые веб-серверы имеют специальную поддержку отправки файлов, называемую X-Sendfile. Идея заключается в перенаправлении запроса на файл на веб-сервер, который будет напрямую обслуживать файл. В результате веб-приложение может завершиться раньше, пока веб-сервер отправляет файл. Для использования этой функции можно вызвать метод yii\web\Response::xSendFile(). Следующий список обобщает, как включить функцию X-Sendfile для некоторых популярных веб-серверов:

  • Apache: X-Sendfile
  • Lighttpd v1.4: X-LIGHTTPD-send-file
  • Lighttpd v1.5: X-Sendfile
  • Nginx: X-Accel-Redirect
  • Cherokee: X-Sendfile и X-Accel-Redirect

Отправка ответа

Содержимое ответа не отправляется пользователю до тех пор, пока не будет вызван метод yii\web\Response::send(). По умолчанию этот метод вызывается автоматически в конце метода yii\base\Application::run(). Однако вы можете явно вызвать этот метод, чтобы немедленно заставить отправить ответ.

Метод yii\web\Response::send() выполняет следующие шаги для отправки ответа:

  1. Вызывает событие yii\web\Response::EVENT_BEFORE_SEND.
  2. Вызывает метод yii\web\Response::prepare() для форматирования данных ответа в содержимое ответа.
  3. Вызывает событие yii\web\Response::EVENT_AFTER_PREPARE.
  4. Вызывает метод yii\web\Response::sendHeaders() для отправки зарегистрированных HTTP-заголовков.
  5. Вызывает метод yii\web\Response::sendContent() для отправки содержимого тела ответа.
  6. Вызывает событие yii\web\Response::EVENT_AFTER_SEND.

После вызова метода yii\web\Response::send() один раз, любые последующие вызовы этого метода будут игнорироваться. Это означает, что после отправки ответа вы не сможете добавить больше содержимого к нему.

Как видите, метод yii\web\Response::send() вызывает несколько полезных событий. Реагируя на эти события, можно настраивать или оформлять ответ.

© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-runtime-responses.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API