2 关注者

响应

当应用程序完成处理一个 请求 时,它会生成一个 响应 对象并将其发送给最终用户。响应对象包含诸如 HTTP 状态码、HTTP 头和主体等信息。Web 应用程序开发的最终目标实质上是在各种请求的基础上构建这样的响应对象。

在大多数情况下,您应该主要处理 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 相关联。以下 HTTP 异常是在 Yii 中预定义的

如果您想要抛出的异常不在上述列表中,您可以通过继承 yii\web\HttpException 创建一个新的异常,或者直接抛出带有状态码的异常,例如:

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

HTTP 头部

您可以通过操作 response 组件中的 header 集合 来发送 HTTP 头部。例如:

$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!';

如果您的数据需要在发送给最终用户之前进行格式化,您应该同时设置 formatdata 属性。 format 属性指定 data 应该以哪种格式进行格式化。例如:

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

Yii 开箱即用地支持以下格式,每种格式都由一个 formatter 类实现。您可以自定义这些格式化程序或添加新的格式化程序,方法是配置 yii\web\Response::$formatters 属性。

虽然响应体可以如上所示显式设置,但在大多数情况下,您可以通过 action 方法的返回值隐式设置它。一个常见的用例如下所示:

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

上面的 index action 返回 index 视图的渲染结果。返回值将被 response 组件获取,格式化,然后发送给最终用户。

因为默认情况下响应格式为 HTML,所以您应该只在 action 方法中返回字符串。如果您想使用不同的响应格式,则应先设置它,然后再返回数据。例如:

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

如前所述,除了使用默认的 response 应用组件之外,您还可以创建自己的响应对象并将其发送给最终用户。您可以通过在 action 方法中返回此类对象来实现,如下所示:

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 对其提供了一些特殊支持。

您可以通过调用 yii\web\Response::redirect() 方法将用户浏览器重定向到某个 URL。该方法使用给定的 URL 设置相应的 Location 头部,并返回响应对象本身。在 action 方法中,您可以调用其快捷版本 yii\web\Controller::redirect()。例如:

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

在上面的代码中,action 方法返回 redirect() 方法的结果。如前所述,action 方法返回的响应对象将用作发送给最终用户的响应。

在 action 方法以外的地方,您应该直接调用 yii\web\Response::redirect(),然后链接调用 yii\web\Response::send() 方法,以确保不会将额外内容附加到响应中。

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

信息:默认情况下, yii\web\Response::redirect() 方法将响应状态码设置为 302,指示浏览器请求的资源暂时位于不同的 URI 中。您可以传入状态码 301 来告诉浏览器资源已永久重定位。

当当前请求是 AJAX 请求时,发送 Location 头部不会自动导致浏览器重定向。为了解决此问题, yii\web\Response::redirect() 方法使用重定向 URL 作为其值的 X-Redirect 头部。在客户端,您可以编写 JavaScript 代码来读取此头部值并相应地重定向浏览器。

信息:Yii 带有一个 yii.js JavaScript 文件,该文件提供了一组常用的 JavaScript 实用程序,包括基于 X-Redirect 头部的浏览器重定向。因此,如果您正在使用此 JavaScript 文件(通过注册 yii\web\YiiAsset asset bundle),则无需编写任何内容来支持 AJAX 重定向。有关 yii.js 的更多信息,请参阅 客户端脚本部分

发送文件

与浏览器重定向类似,文件发送是另一个依赖于特定 HTTP 头部的功能。Yii 提供了一组方法来支持各种文件发送需求。它们都内置支持 HTTP 范围头部。

这些方法具有相同的函数签名,响应对象作为返回值。如果要发送的文件非常大,您应该考虑使用 yii\web\Response::sendStreamAsFile(),因为它更节省内存。以下示例显示了如何在控制器 action 中发送文件:

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

如果您在 action 方法以外的地方调用文件发送方法,您也应该随后调用 yii\web\Response::send() 方法,以确保不会将额外内容附加到响应中。

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

某些 Web 服务器具有称为X-Sendfile的特殊文件发送支持。其思想是将对文件的请求重定向到 Web 服务器,Web 服务器将直接提供文件。因此,Web 应用程序可以更早地终止,而 Web 服务器正在发送文件。要使用此功能,您可以调用 yii\web\Response::xSendFile()。以下列表总结了如何为一些流行的 Web 服务器启用 X-Sendfile 功能:

发送响应

响应中的内容只有在调用 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() 方法触发了一些有用的事件。通过响应这些事件,可以调整或装饰响应。

发现错别字或您认为此页面需要改进?
在 github 上编辑它 !