Cookie
HTTP Cookie (网页 Cookie、浏览器 Cookie)是服务器发送到用户浏览器的一小段数据。浏览器会存储该数据并在后续向同一服务器发起请求时将其带回。通常用于判断两个请求是否来自同一浏览器——例如保持用户登录状态。它为无状态的 HTTP 协议提供了状态信息记忆能力。
Cookies 主要用于以下三个场景:
会话管理:登录状态、购物车、游戏分数等需要服务器记忆的信息
个性化设置:用户偏好、主题及其他配置
行为追踪:记录和分析用户行为
为帮助你高效地向浏览器发送 Cookies,CodeIgniter 提供了 CodeIgniter\Cookie\Cookie 类来抽象化 Cookie 交互。
创建 Cookie
目前有四种方式创建新的 Cookie 值对象:
<?php use CodeIgniter\Cookie\Cookie; use DateTime; // Using the constructor $cookie = new Cookie( 'remember_token', 'f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6', [ 'expires' => new DateTime('+2 hours'), 'prefix' => '__Secure-', 'path' => '/', 'domain' => '', 'secure' => true, 'httponly' => true, 'raw' => false, 'samesite' => Cookie::SAMESITE_LAX, ], ); // Supplying a Set-Cookie header string $cookie = Cookie::fromHeaderString( 'remember_token=f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6; Path=/; Secure; HttpOnly; SameSite=Lax', false, // raw ); // Using the fluent builder interface $cookie = (new Cookie('remember_token')) ->withValue('f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6') ->withPrefix('__Secure-') ->withExpires(new DateTime('+2 hours')) ->withPath('/') ->withDomain('') ->withSecure(true) ->withHTTPOnly(true) ->withSameSite(Cookie::SAMESITE_LAX); // Using the global function `cookie` which implicitly calls `new Cookie()` $cookie = cookie('remember_token', 'f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6');
构建 Cookie 对象时,仅 name 属性为必填项,其他属性均为可选。若未修改可选属性,它们的值将由 Cookie 类中保存的默认值填充。
覆盖默认值
要覆盖类中存储的默认值,可以通过静态方法 Cookie::setDefaults() 传入 Config\Cookie 实例或包含默认值的数组:
<?php use CodeIgniter\Cookie\Cookie; use Config\Cookie as CookieConfig; // pass in a Config\Cookie instance before constructing a Cookie class Cookie::setDefaults(config(CookieConfig::class)); $cookie = new Cookie('login_token'); // pass in an array of defaults $myDefaults = [ 'expires' => 0, 'samesite' => Cookie::SAMESITE_STRICT, ]; Cookie::setDefaults($myDefaults); $cookie = new Cookie('login_token');
向 Cookie::setDefaults() 传递 Config\Cookie 实例或数组将永久覆盖默认值,直到传入新的默认值为止。
临时修改默认值
若希望临时修改默认值而非永久覆盖,可利用 Cookie::setDefaults() 返回旧默认值数组的特性:
<?php use CodeIgniter\Cookie\Cookie; use Config\Cookie as CookieConfig; $oldDefaults = Cookie::setDefaults(config(CookieConfig::class)); $cookie = new Cookie('my_token', 'muffins'); // return the old defaults Cookie::setDefaults($oldDefaults);
访问 Cookie 属性
实例化后,可通过 getter 方法轻松访问 Cookie 属性:
<?php use CodeIgniter\Cookie\Cookie; use DateTime; use DateTimeZone; $cookie = new Cookie( 'remember_token', 'f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6', [ 'expires' => new DateTime('2025年02月14日 00:00:00', new DateTimeZone('UTC')), 'prefix' => '__Secure-', 'path' => '/', 'domain' => '', 'secure' => true, 'httponly' => true, 'raw' => false, 'samesite' => Cookie::SAMESITE_LAX, ], ); $cookie->getName(); // 'remember_token' $cookie->getPrefix(); // '__Secure-' $cookie->getPrefixedName(); // '__Secure-remember_token' $cookie->getExpiresTimestamp(); // UNIX timestamp $cookie->getExpiresString(); // 'Fri, 14-Feb-2025 00:00:00 GMT' $cookie->isExpired(); // false $cookie->getMaxAge(); // the difference from time() to expires $cookie->isRaw(); // false $cookie->isSecure(); // true $cookie->getPath(); // '/' $cookie->getDomain(); // '' $cookie->isHTTPOnly(); // true $cookie->getSameSite(); // 'Lax' // additional getter $cookie->getId(); // '__Secure-remember_token;;/' // when using `setcookie()`'s alternative signature on PHP 7.3+ // you can easily use the `getOptions()` method to supply the // $options parameter $cookie->getOptions();
不可变 Cookie
Cookie 实例是 HTTP Cookie 的不可变值对象。由于其不可变性,修改实例属性不会影响原实例,修改操作 始终 返回新实例。需保留新实例方可使用:
<?php use CodeIgniter\Cookie\Cookie; $cookie = new Cookie('login_token', 'admin'); $cookie->getName(); // 'login_token' $cookie->withName('remember_token'); $cookie->getName(); // 'login_token' $new = $cookie->withName('remember_token'); $new->getName(); // 'remember_token'
验证 Cookie 属性
HTTP Cookie 受多个规范约束以确保浏览器接受。因此在创建或修改 Cookie 的某些属性时,会进行规范符合性验证。若验证失败将抛出 CookieException。
验证名称属性
Cookie 名称可为任意 US-ASCII 字符,但以下字符除外:
控制字符
空格或制表符
分隔字符:
( ) < > @ , ; : \ " / [ ] ? = { }
若设置 $raw 参数为 true 将执行严格验证,因为 PHP 的 setcookie() 和 setrawcookie() 会拒绝无效名称。此外,名称不能为空字符串。
验证前缀属性
使用 __Secure- 前缀时,必须设置 $secure 标志为 true。使用 __Host- 前缀时需满足:
$secure标志设为true$domain为空$path必须为/
验证 SameSite 属性
SameSite 属性接受三个值:
Lax (宽松模式):跨站子请求(如图片加载)不发送 Cookie,但导航到源站时(如点击链接)会发送
Strict (严格模式):仅在第一方上下文中发送 Cookie
None (无限制):所有上下文中均发送 Cookie
CodeIgniter 允许将 SameSite 设为空字符串,此时使用 Cookie 类保存的默认值。可通过上文所述的 Cookie::setDefaults() 修改默认值。
现代浏览器规范要求未指定 SameSite 时默认使用 Lax。若 SameSite 设为空字符串且默认值也为空,则 Cookie 将被赋予 Lax 值。
当设置 SameSite 为 None 时,必须同时设置 Secure 为 true。
Cookie 类接受不区分大小写的 SameSite 值,也可使用类常量简化操作:
<?php use CodeIgniter\Cookie\Cookie; Cookie::SAMESITE_LAX; // 'lax' Cookie::SAMESITE_STRICT; // 'strict' Cookie::SAMESITE_NONE; // 'none'
发送 Cookie
将 Cookie 对象存入 Response 对象的 CookieStore 中,框架会自动发送 Cookie。
使用 CodeIgniter\HTTP\Response::setCookie() 设置:
<?php use CodeIgniter\Cookie\Cookie; $response = service('response'); $cookie = new Cookie( 'remember_token', 'f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6', [ 'max-age' => 3600 * 2, // Expires in 2 hours ], ); $response->setCookie($cookie);
也可使用 set_cookie() 辅助函数:
<?php use CodeIgniter\Cookie\Cookie; helper('cookie'); $cookie = new Cookie( 'remember_token', 'f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6', [ 'max-age' => 3600 * 2, // Expires in 2 hours ], ); set_cookie($cookie);
使用 Cookie 存储库
备注
通常无需直接操作 CookieStore。
CookieStore 类表示 Cookie 对象的不可变集合。
从 Response 获取存储库
可通过当前 Response 对象访问 CookieStore 实例:
<?php $cookieStore = service('response')->getCookieStore();
创建 CookieStore
CodeIgniter 提供三种方式创建新 CookieStore 实例:
<?php use CodeIgniter\Cookie\Cookie; use CodeIgniter\Cookie\CookieStore; // Passing an array of `Cookie` objects in the constructor $store = new CookieStore([ new Cookie('login_token'), new Cookie('remember_token'), ]); // Passing an array of `Set-Cookie` header strings $store = CookieStore::fromCookieHeaders([ 'remember_token=me; Path=/; SameSite=Lax', 'login_token=admin; Path=/; SameSite=Lax', ]); // using the global `cookies` function $store = cookies([new Cookie('login_token')], false); // retrieving the `CookieStore` instance saved in our current `Response` object $store = cookies();
备注
使用全局函数 cookies() 时,仅当第二个参数 $getGlobal 设为 false 时才会考虑传入的 Cookie 数组。
检查存储库中的 Cookie
可通过多种方式检查 CookieStore 实例中是否存在某 Cookie 对象:
<?php use CodeIgniter\Cookie\Cookie; use CodeIgniter\Cookie\CookieStore; // check if cookie is in the current cookie collection $store = new CookieStore([ new Cookie('login_token'), new Cookie('remember_token'), ]); $store->has('login_token'); // check if cookie is in the current Response's cookie collection cookies()->has('login_token'); service('response')->hasCookie('remember_token'); // using the cookie helper to check the current Response // not available to v4.1.1 and lower helper('cookie'); has_cookie('login_token');
获取存储库中的 Cookie
从 Cookie 集合中检索 Cookie 实例非常简单:
<?php use CodeIgniter\Cookie\Cookie; use CodeIgniter\Cookie\CookieStore; use Config\Services; // getting cookie in the current cookie collection $store = new CookieStore([ new Cookie('login_token'), new Cookie('remember_token'), ]); $store->get('login_token'); // getting cookie in the current Response's cookie collection cookies()->get('login_token'); service('response')->getCookie('remember_token'); // using the cookie helper to get cookie from the Response's cookie collection helper('cookie'); get_cookie('remember_token');
直接从 CookieStore 获取实例时,无效名称会抛出 CookieException:
<?php // throws CookieException $store->get('unknown_cookie');
从当前 Response 的 Cookie 集合获取时,无效名称返回 null:
<?php cookies()->get('unknown_cookie'); // null
若从 Response 获取时不带参数,将显示存储库中所有 Cookie 对象:
<?php cookies()->display(); // array of Cookie objects // or even from the Response service('response')->getCookies();
备注
辅助函数 get_cookie() 从当前 Request 对象而非 Response 获取 Cookie。该函数检查 $_COOKIE 数组并直接获取。
添加/删除存储库中的 Cookie
如前所述,CookieStore 对象不可变。需保存修改后的实例才能生效,原实例保持不变:
<?php use CodeIgniter\Cookie\Cookie; use CodeIgniter\Cookie\CookieStore; $store = new CookieStore([ new Cookie('login_token'), new Cookie('remember_token'), ]); // adding a new Cookie instance $new = $store->put(new Cookie('admin_token', 'yes')); // removing a Cookie instance $new = $store->remove('login_token');
备注
从存储库删除 Cookie 不会 从浏览器删除。若要从浏览器删除 Cookie,必须向存储库添加同名空值 Cookie。
与当前 Response 对象中的 Cookies 交互时,可安全添加/删除 Cookies,无需担心集合的不可变性。Response 对象会自动替换为修改后的实例:
<?php service('response')->setCookie('admin_token', 'yes'); service('response')->deleteCookie('login_token'); // using the cookie helper helper('cookie'); set_cookie('admin_token', 'yes'); delete_cookie('login_token');
分发存储库中的 Cookie
重要
该方法在 4.1.6 版本弃用,4.6.0 版本移除。
通常无需手动发送 Cookie,CodeIgniter 会自动处理。如需手动发送,可使用 dispatch 方法。需通过 headers_sent() 检查确保标头未发送:
<?php use CodeIgniter\Cookie\Cookie; use CodeIgniter\Cookie\CookieStore; $store = new CookieStore([ new Cookie('login_token'), new Cookie('remember_token'), ]); $store->dispatch(); // After dispatch, the collection is now empty.
Cookie 个性化配置
Cookie 类已预设合理默认值以确保正常创建。可通过修改 app/Config/Cookie.php 中的 Config\Cookie 类配置项来自定义:
设置项 |
选项/类型 |
默认值 |
描述 |
|---|---|---|---|
$prefix |
|
|
Cookie 名前缀 |
$expires |
|
|
过期时间戳 |
$path |
|
|
Cookie 路径属性 |
$domain |
|
|
Cookie 域名属性(带尾部斜线) |
$secure |
|
|
是否仅通过 HTTPS 发送 |
$httponly |
|
|
是否禁止 JavaScript 访问 |
$samesite |
|
|
SameSite 属性 |
$raw |
|
|
是否使用 |
运行时可通过 Cookie::setDefaults() 方法手动设置新默认值。
类参考
- class CodeIgniter\Cookie\Cookie
- static setDefaults([$config = []])
- 参数:
$config (
\Config\Cookie|array) – 配置数组或实例
- 返回类型:
array- 返回:
旧默认值数组
通过注入
Config\Cookie配置或数组来设置 Cookie 实例的默认属性。
- static fromHeaderString(string $header[, bool $raw = false])
- 参数:
$header (
string) –Set-Cookie标头字符串$raw (
bool) – 是否使用原始 Cookie
- 返回类型:
Cookie- 返回:
Cookie实例- Throws:
CookieException
从
Set-Cookie标头创建新 Cookie 实例。
- __construct(string $name[, string $value = ''[, array $options = []]])
- 参数:
$name (
string) – Cookie 名称$value (
string) – Cookie 值$options (
array) – Cookie 选项
- 返回类型:
Cookie- 返回:
Cookie实例- Throws:
CookieException
构造新 Cookie 实例。
- getId()
- 返回类型:
string- 返回:
用于 Cookie 集合索引的 ID
- getPrefix() → string
- getName() → string
- getPrefixedName() → string
- getValue() → string
- getExpiresTimestamp() → int
- getExpiresString() → string
- isExpired() → bool
- getMaxAge() → int
- getDomain() → string
- getPath() → string
- isSecure() → bool
- isHTTPOnly() → bool
- getSameSite() → string
- isRaw() → bool
- getOptions() → array
- withRaw([bool $raw = true])
- 参数:
$raw (
bool) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带更新 URL 编码选项的新 Cookie。
- withPrefix([string $prefix = ''])
- 参数:
$prefix (
string) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新前缀的 Cookie。
- withName(string $name)
- 参数:
$name (
string) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新名称的 Cookie。
- withValue(string $value)
- 参数:
$value (
string) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新值的 Cookie。
- withExpires($expires)
- 参数:
$expires (
DateTimeInterface|string|int) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新过期时间的 Cookie。
- withExpired()
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建即将过期的 Cookie。
- withNeverExpiring()
重要
该方法在 4.2.6 版本弃用,4.6.0 版本移除。
- 参数:
$name (
string) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建永不过期的 Cookie(已移除)。
- withDomain(?string $domain)
- 参数:
$domain (
string|null) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新域名的 Cookie。
- withPath(?string $path)
- 参数:
$path (
string|null) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新路径的 Cookie。
- withSecure([bool $secure = true])
- 参数:
$secure (
bool) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新 "Secure" 属性的 Cookie。
- withHTTPOnly([bool $httponly = true])
- 参数:
$httponly (
bool) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新 "HttpOnly" 属性的 Cookie。
- withSameSite(string $samesite)
- 参数:
$samesite (
string) –
- 返回类型:
Cookie- 返回:
新
Cookie实例
创建带新 "SameSite" 属性的 Cookie。
- toHeaderString()
- 返回类型:
string- 返回:
可作为标头字符串传递的字符串表示
- toArray()
- 返回类型:
array- 返回:
Cookie 实例的数组表示
- class CodeIgniter\Cookie\CookieStore
- static fromCookieHeaders(array $headers[, bool $raw = false])
- 参数:
$header (
array) –Set-Cookie标头数组$raw (
bool) – 是否使用原始 Cookie
- 返回类型:
CookieStore- 返回:
CookieStore实例- Throws:
CookieException
从
Set-Cookie标头数组创建 CookieStore。
- __construct(array $cookies)
- 参数:
$cookies (
array) – Cookie 对象数组
- 返回类型:
CookieStore- 返回:
CookieStore实例- Throws:
CookieException
- has(string $name[, string $prefix = ''[, ?string $value = null]]) → bool
- 参数:
$name (
string) – Cookie 名称$prefix (
string) – Cookie 前缀$value (
string|null) – Cookie 值
- 返回类型:
bool- 返回:
检查指定名称和前缀的 Cookie 是否存在
- get(string $name[, string $prefix = '']) → Cookie
- 参数:
$name (
string) – Cookie 名称$prefix (
string) – Cookie 前缀
- 返回类型:
Cookie- 返回:
获取指定名称和前缀的 Cookie 实例
- Throws:
CookieException
- put(Cookie $cookie) → CookieStore
- 参数:
$cookie (
Cookie) – Cookie 对象
- 返回类型:
CookieStore- 返回:
新
CookieStore实例
存储新 Cookie 并返回新集合,原集合保持不变。
- remove(string $name[, string $prefix = '']) → CookieStore
- 参数:
$name (
string) – Cookie 名称$prefix (
string) – Cookie 前缀
- 返回类型:
CookieStore- 返回:
新
CookieStore实例
移除 Cookie 并返回新集合,原集合保持不变。
- dispatch() → void
重要
该方法在 4.1.6 版本弃用,4.6.0 版本移除。
- 返回类型:
void
分发存储库中所有 Cookies(已移除)。
- display() → array
- 返回类型:
array- 返回:
返回存储中的所有 Ccookie
- clear() → void
- 返回类型:
void
清除 Cookie 集合。