HTTP 响应
Response 类继承自 HTTP 消息类,并添加了仅适用于服务器响应客户端请求的方法。
使用响应类
系统会自动为你实例化一个 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,并设置相应的内容类型头部。通常你会发送一个待转换的数据数组:
<?php
$data = [
'success' => true,
'id' => 123,
];
return $this->response->setJSON($data);
// or
return $this->response->setXML($data);
设置头部
setHeader()
通常需要为响应设置头部。Response 类通过 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 中包含需要移除的片段,可以在方法中使用 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);
备注
由于漏洞,在 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 规范内置了帮助客户端(通常是浏览器)缓存结果的工具。正确使用可以极大提升应用性能,因为它会告知客户端无需联系服务器(当内容未变化时)。
这通过 Cache-Control
和 ETag
头部实现。本指南不深入讲解所有缓存头部,但你可以通过 Google 开发者文档 获得详细理解。
默认情况下,CodeIgniter 发送的所有响应对象都关闭了 HTTP 缓存。由于场景差异过大,我们选择关闭作为默认设置。你可以通过 setCache()
方法轻松设置所需缓存值:
<?php
$options = [
'max-age' => 300,
's-maxage' => 900,
'etag' => 'abcde',
];
$this->response->setCache($options);
$options
数组接收键值对,除个别例外,这些参数会被分配到 Cache-Control
头部。你可以根据具体需求自由设置所有选项。虽然大多数选项应用于 Cache-Control
头部,但该方法会智能处理 etag
和 last-modified
选项到对应头部。
类参考
备注
除了列出的方法外,此类继承自 消息类 的方法。
继承自消息类的方法包括:
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
头部,包括ETags
和Last-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 传输。设为null
时使用 app/Config/Cookie.php 的默认值$httponly (
bool
) – 是否仅允许 HTTP 请求访问(禁止 JavaScript)。设为null
时使用 app/Config/Cookie.php 的默认值$samesite (
string
) – SameSite 参数值。设为''
时不设置该属性。设为null
时使用 app/Config/Cookie.php 的默认值
- 返回类型:
void
备注
在 v4.2.7 之前,由于漏洞,
$secure
和$httponly
的默认值为false
,且 app/Config/Cookie.php 中的值未被使用。向响应实例设置包含指定值的 Cookie。
有两种传递信息设置 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);
仅需
name
和value
。要删除 Cookie 可将value
设为空。expire
以秒为单位,会添加到当前时间。请勿包含具体时间,只需设置从现在起有效的秒数。设为0
时 Cookie 仅在浏览器打开期间有效。备注
但如果
value
设为空字符串且expire
为0
,Cookie 将被删除。要为整个站点设置 Cookie(无论请求方式),域名前加句点,如:.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 来删除 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
检查响应是否包含指定 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[]
返回响应实例中当前设置的所有 Cookie。 这些是你在本次请求中明确指定要设置的 Cookie。