HTTP 响应

Response 类继承自 HTTP Message 类,并添加了仅适用于服务端响应客户端请求的方法。

使用 Response 类

Response 类会在控制器实例化时自动传入,可通过 $this->response 访问。它与 Services::response() 返回的是同一实例,称为全局响应实例。

多数情况下无需直接操作此类,CodeIgniter 会自动发送标头和正文。页面成功创建所需内容时,这种自动处理非常理想。但当出现错误、需要返回特定状态码,或使用强大的 HTTP 缓存功能时,就可以直接操作此实例。

设置输出

需要直接设置脚本输出而非依赖 CodeIgniter 自动设置时,可使用 setBody 方法。通常与设置响应状态码配合使用:

<?php

$this->response->setStatusCode(404)->setBody($body);

原因短语('OK'、'Created'、'Moved Permanently')会自动添加,但也可在 setStatusCode() 方法的第二个参数中自定义:

<?php

$this->response->setStatusCode(404, 'Nope. Not here.');

使用 setJSON()setXML() 方法可将数组格式化为 JSON 或 XML,并将 Content-Type 标头设置为对应的 MIME 类型。通常需要发送待转换的数组数据:

<?php

$data = [
    'success' => true,
    'id'      => 123,
];

return $this->response->setJSON($data);

// or
return $this->response->setXML($data);

设置标头

setHeader()

设置响应标头时,可使用 setHeader() 方法。

第一个参数为标头名称,第二个参数为值,可以是字符串或字符串数组,发送给客户端时会自动合并。

<?php

$this->response->setHeader('Location', 'http://example.com')
    ->setHeader('WWW-Authenticate', 'Negotiate');

使用这些方法而非 PHP 原生函数可避免标头过早发送导致错误,同时使测试成为可能。

重要

v4.6.0 起,如果先使用 PHP 原生 header() 函数设置标头,再使用 Response 类设置同一标头,之前的标头将被覆盖。

备注

此方法仅设置标头到响应实例。因此,如果创建并返回另一个响应实例(例如调用 redirect()),此处设置的标头不会自动发送。

appendHeader()

如果标头已存在且可包含多个值,可使用 appendHeader()prependHeader() 方法分别在值列表末尾或开头添加新值。第一个参数为标头名称,第二个参数为待追加或前置的值。

<?php

$this->response->setHeader('Cache-Control', 'no-cache')
    ->appendHeader('Cache-Control', 'must-revalidate');

removeHeader()

使用 removeHeader() 方法可移除响应标头,该方法仅接受标头名称作为参数,不区分大小写。

<?php

$this->response->removeHeader('Location');

重定向

如需创建重定向,请使用 redirect() 函数。

该函数返回 RedirectResponse 实例。此实例与 Services::response() 返回的全局响应实例不同。

警告

如果在调用 redirect() 之前设置了 Cookie 或响应标头,它们会设置到全局响应实例,不会自动复制到 RedirectResponse 实例。要发送它们,需要手动调用 withCookies()withHeaders() 方法。

重要

如需重定向,必须在 控制器控制器过滤器 的方法中返回 RedirectResponse 实例。注意 __construct()initController() 方法无法返回任何值。如果忘记返回 RedirectResponse,重定向不会执行。

重定向到 URI 路径

传递相对于 baseURL 的 URI 路径时,使用 redirect()->to()

// Go to specific URI path. "admin/home" is the URI path relative to baseURL.
return redirect()->to('admin/home');

备注

如果 URL 中包含需移除的 fragment,可在方法中使用 refresh 参数。 例如 return redirect()->to('admin/home', null, 'refresh');

重定向到已定义的路由

传递 路由名称 或用于 反向路由 的 Controller::method 时,使用 redirect()->route()

// Go to a named route. "user_gallery" is the route name, not a URI path.
return redirect()->route('user_gallery');

向函数传递单个参数时,会作为路由名称或 Controller::method 进行反向路由处理,而非相对/完整 URI,效果与 redirect()->route() 相同:

// Go to a named/reverse-routed URI.
return redirect('named_route');

返回上一页

返回上一页时,使用 redirect()->back()

// Go back to the previous page.
return redirect()->back();

// Keep the old input values upon redirect so they can be used by the `old()` function.
return redirect()->back()->withInput();

// Set a flash message.
return redirect()->back()->with('foo', 'message');

备注

redirect()->back() 与浏览器"后退"按钮不同。Session 可用时,会跳转到"Session 期间上次访问的页面"。如果 Session 未加载或不可用,则使用 HTTP_REFERER 的安全过滤版本。

带标头的重定向

在调用 redirect() 之前设置的响应标头会设置到全局响应实例,不会自动复制到 RedirectResponse 实例。

要发送标头,需手动调用 withHeaders() 方法。

// Copies all headers from the global response instance.
return redirect()->back()->withHeaders();

重定向状态码

GET 请求的默认 HTTP 状态码为 302。但使用 HTTP/1.1 或更高版本时,POST/PUT/DELETE 请求使用 303,其他请求使用 307。

可指定状态码:

// Redirect to a URI path relative to baseURL with status code 301.
return redirect()->to('admin/home', 301);

// Redirect to a route with status code 308.
return redirect()->route('user_gallery', [], 308);

// Redirect back with status code 302.
return redirect()->back(302);

备注

由于 Bug,v4.3.3 或更早的版本中,即使指定了状态码,实际重定向响应的状态码可能会被更改。详见 变更记录 v4.3.4

如果不了解 HTTP 重定向状态码,建议阅读 HTTP 重定向

强制文件下载

Response 类提供了简便的方式向客户端发送文件,提示浏览器下载数据到本地。此方法会设置相应的标头来完成下载。

第一个参数为 下载文件的名称,第二个参数为文件数据。

如果第二个参数设为 null,且 $filename 是存在的、可读的文件路径,则会读取该文件内容代替。

如果第三个参数设为 true,则会发送实际的文件 MIME 类型(基于文件名后缀),以便浏览器有对应的处理程序时可直接使用。

示例:

<?php

$data = 'Here is some text!';
$name = 'mytext.txt';

return $this->response->download($name, $data);

如需下载服务器上已有的文件,需将第二个参数显式设为 null

<?php

// Contents of photo.jpg will be automatically read
return $this->response->download('/path/to/photo.jpg', null);

使用可选的 setFileName() 方法可更改发送到浏览器的文件名:

<?php

return $this->response->download('awkwardEncryptedFileName.fakeExt', null)->setFileName('expenses.csv');

备注

响应对象必须被返回才能发送下载内容到客户端。由此响应可经过所有 after 过滤器后再发送给客户端。

在浏览器中打开文件

部分浏览器可显示 PDF 等文件。如需让浏览器直接显示而非保存文件,可调用 DownloadResponse::inline() 方法。

<?php

$data = 'Here is some text!';
$name = 'mytext.txt';

return $this->response->download($name, $data)->inline();

HTTP 缓存

HTTP 规范内置了帮助客户端(通常为 Web 浏览器)缓存结果的工具。正确使用可大幅提升应用性能,因为客户端在内容未变更时无需再与服务端通信。没有比这更快的响应速度了。

通过 Cache-ControlETag 标头来实现缓存。本指南不适合深入介绍所有缓存标头,可在 Google 开发者文档 获取详细说明。

默认情况下,通过 CodeIgniter 发送的所有响应对象都关闭了 HTTP 缓存。由于缓存选项和使用场景过于多样,无法设定合适的默认值,因此默认关闭。使用 setCache() 方法即可轻松设置所需的缓存值:

<?php

$options = [
    'max-age'  => 300,
    's-maxage' => 900,
    'etag'     => 'abcde',
];
$this->response->setCache($options);

$options 接收关联数组形式的缓存控制选项(少数例外),主要应用于 Cache-Control 标头。可根据具体需求自由设置所有选项。虽然多数选项应用于 Cache-Control 标头,但 etaglast-modified 选项会智能地分配到对应的标头。

类参考

备注

除以下列出的方法外,此类还继承了 Message 类 的方法。

继承自 Message 类的方法:

  • CodeIgniter\HTTP\Message::body()

  • CodeIgniter\HTTP\Message::setBody()

  • CodeIgniter\HTTP\Message::populateHeaders()

  • CodeIgniter\HTTP\Message::headers()

  • CodeIgniter\HTTP\Message::header()

  • CodeIgniter\HTTP\Message::headerLine()

  • CodeIgniter\HTTP\Message::setHeader()

  • CodeIgniter\HTTP\Message::removeHeader()

  • CodeIgniter\HTTP\Message::appendHeader()

  • CodeIgniter\HTTP\Message::protocolVersion()

  • CodeIgniter\HTTP\Message::setProtocolVersion()

  • CodeIgniter\HTTP\Message::negotiateMedia()

  • CodeIgniter\HTTP\Message::negotiateCharset()

  • CodeIgniter\HTTP\Message::negotiateEncoding()

  • CodeIgniter\HTTP\Message::negotiateLanguage()

  • CodeIgniter\HTTP\Message::negotiateLanguage()

class CodeIgniter\HTTP\Response
getStatusCode()
返回:

当前响应的 HTTP 状态码

返回类型:

int

返回当前响应的状态码。如果未设置状态码,将抛出 BadMethodCallException:

<?php

echo $response->getStatusCode();
setStatusCode($code[, $reason=''])
参数:
  • $code (int) -- HTTP 状态码

  • $reason (string) -- 可选的原因短语

返回:

当前 Response 实例

返回类型:

CodeIgniter\HTTP\Response

设置响应应发送的 HTTP 状态码:

<?php

$response->setStatusCode(404);

原因短语会根据官方列表自动生成。如需为自定义状态码设置原因短语,可将其作为第二个参数传入:

<?php

$response->setStatusCode(230, 'Tardis initiated');
getReasonPhrase()
返回:

当前原因短语

返回类型:

string

返回当前响应的状态码。如果未设置状态码,将返回空字符串:

<?php

echo $response->getReasonPhrase();
setDate($date)
参数:
  • $date (DateTime) -- 用于设置响应时间的 DateTime 实例

返回:

当前响应实例

返回类型:

CodeIgniter\HTTP\Response

设置响应的日期。$date 参数必须是 DateTime 实例。

setContentType($mime[, $charset='UTF-8'])
参数:
  • $mime (string) -- 响应表示的内容类型

  • $charset (string) -- 响应使用的字符集

返回:

当前响应实例

返回类型:

CodeIgniter\HTTP\Response

设置响应的内容类型:

<?php

$response->setContentType('text/plain');
$response->setContentType('text/html');
$response->setContentType('application/json');

默认情况下,方法将字符集设为 UTF-8。如需更改,可在第二个参数中传入字符集:

<?php

$response->setContentType('text/plain', 'x-pig-latin');
noCache()
返回:

当前响应实例

返回类型:

CodeIgniter\HTTP\Response

设置 Cache-Control 标头以关闭所有 HTTP 缓存。这是所有响应消息的默认设置:

<?php

$response->noCache();
/*
 * Sets the following header:
 * Cache-Control: no-store, max-age=0, no-cache
 */
setCache($options)
参数:
  • $options (array) -- 关联数组形式的缓存控制选项

返回:

当前响应实例

返回类型:

CodeIgniter\HTTP\Response

设置 Cache-Control 标头,包括 ETagsLast-Modified。常用选项:

  • etag

  • last-modified

  • max-age

  • s-maxage

  • private

  • public

  • must-revalidate

  • proxy-revalidate

  • no-transform

传递 last-modified 选项时,可以是日期字符串或 DateTime 对象。

setLastModified($date)
参数:
  • $date (string|DateTime) -- 用于设置 Last-Modified 标头的日期

返回:

当前响应实例

返回类型:

CodeIgniter\HTTP\Response

设置 Last-Modified 标头。$date 对象可以是字符串或 DateTime 实例:

<?php

$response->setLastModified(date('D, d M Y H:i:s'));
$response->setLastModified(\DateTime::createFromFormat('!U', $timestamp));
send() Response
返回:

当前响应实例

返回类型:

CodeIgniter\HTTP\Response

告知响应将所有内容发送回客户端。会先发送标头,再发送响应正文。主应用的响应由 CodeIgniter 自动处理,无需手动调用此方法。

setCookie($name = ''[, $value = ''[, $expire = 0[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = false[, $httponly = false[, $samesite = null]]]]]]]])
参数:
  • $name (array|Cookie|string) -- Cookie 名称,或包含此方法所有可用参数的关联数组,或 CodeIgniter\Cookie\Cookie 实例

  • $value (string) -- Cookie 值

  • $expire (int) -- Cookie 过期时间(秒)。设为 0 时 Cookie 仅在浏览器打开期间有效

  • $domain (string) -- Cookie 域名

  • $path (string) -- Cookie 路径

  • $prefix (string) -- Cookie 名称前缀。设为 '' 时使用 app/Config/Cookie.php 中的默认值

  • $secure (bool) -- 是否仅通过 HTTPS 传输 Cookie。设为 null 时使用 app/Config/Cookie.php 中的默认值

  • $httponly (bool) -- 是否仅允许 HTTP 请求访问 Cookie(禁止 JavaScript)。设为 null 时使用 app/Config/Cookie.php 中的默认值

  • $samesite (string) -- SameSite Cookie 参数的值。设为 '' 时不设置 SameSite 属性。设为 null 时使用 app/Config/Cookie.php 中的默认值

返回类型:

void

备注

v4.2.7 之前,由于 Bug,$secure$httponly 默认值为 false,从未使用 app/Config/Cookie.php 中的值。

将指定值的 Cookie 设置到 Response 实例。

有两种方式可传递信息以设置 Cookie:数组方式和独立参数方式:

数组方式

此方式下,关联数组作为第一个参数传入:

<?php

$cookie = [
    'name'     => 'The Cookie Name',
    'value'    => 'The Value',
    'expire'   => 86500,
    'domain'   => '.some-domain.com',
    'path'     => '/',
    'prefix'   => 'myprefix_',
    'secure'   => true,
    'httponly' => false,
    'samesite' => 'Lax',
];

$response->setCookie($cookie);

namevalue 是必需的。要删除 Cookie 可将其 value 设为空。

expire 为单位设置,会加到当前时间上。不要包含具体时间,而是填入从 此刻 起 Cookie 有效的秒数。如果 expire 设为零,Cookie 仅在浏览器打开期间有效。

备注

但如果 value 设为空字符串且 expire 设为 0,Cookie 将被删除。

无论站点如何被访问,要设置全站 Cookie,可在 domain 前加点,例如: .your-domain.com

通常无需设置 path,因为方法默认使用根路径。

仅当需要避免服务器同名 Cookie 冲突时才需要 prefix

仅当需要设为安全 Cookie 时,才将 secure 标志设为 true

samesite 值控制 Cookie 如何在域名和子域名之间共享。允许值为 'None''Lax''Strict' 或空字符串 ''。设为空字符串时,将设置默认 SameSite 属性。

独立参数方式

也可通过独立参数设置 Cookie:

<?php

$response->setCookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httponly, $samesite);
deleteCookie($name = ''[, $domain = ''[, $path = '/'[, $prefix = '']]])
参数:
  • $name (mixed) -- Cookie 名称或参数数组

  • $domain (string) -- Cookie 域名

  • $path (string) -- Cookie 路径

  • $prefix (string) -- Cookie 名称前缀

返回类型:

void

删除已有 Cookie。

备注

此方法仅设置浏览器端删除 Cookie 的响应。

name 是必需的。

仅当需要避免服务器同名 Cookie 冲突时才需要 prefix

提供 prefix 时,仅删除该前缀下的 Cookie。 提供 domain 时,仅删除该域名下的 Cookie。 提供 path 时,仅删除该路径下的 Cookie。

如果可选参数留空,则删除所有匹配名称的 Cookie。

示例:

<?php

$response->deleteCookie($name);
hasCookie($name = ''[, $value = null[, $prefix = '']])
参数:
  • $name (mixed) -- Cookie 名称或参数数组

  • $value (string) -- Cookie 值

  • $prefix (string) -- Cookie 名称前缀

返回类型:

bool

检查 Response 是否包含指定的 Cookie。

说明

name 是必需的。如果指定了 prefix,会加到 Cookie 名称前。

未提供 value 时,仅检查 Cookie 是否存在。 提供了 value 时,检查 Cookie 是否存在且值匹配。

示例:

<?php

if ($response->hasCookie($name)) {
    // ...
}
getCookie($name = ''[, $prefix = ''])
参数:
  • $name (string) -- Cookie 名称

  • $prefix (string) -- Cookie 名称前缀

返回类型:

Cookie|Cookie[]|null

返回指定的 Cookie,未找到时返回 null。 未提供 name 时,返回 Cookie 对象数组。

示例:

<?php

$cookie = $response->getCookie($name);
getCookies()
返回类型:

Cookie[]

返回当前 Response 实例中设置的所有 Cookie。 其中仅包含当前请求中明确指定要设置的 Cookie。