setcookie

(PHP 4, PHP 5, PHP 7, PHP 8)

setcookie发送 Cookie

说明

setcookie(
    string $name,
    string $value = "",
    int $expires_or_options = 0,
    string $path = "",
    string $domain = "",
    bool $secure = false,
    bool $httponly = false
): bool

自 PHP 7.3.0 起可用的替代签名(不支持命名参数):

setcookie(string $name, string $value = "", array $options = []): bool

setcookie() 定义了 Cookie,会和剩下的消息头一起发送给客户端。和其他消息头一样,必须在脚本产生任意输出之前发送 Cookie(由于协议的限制)。请在产生任何输出之前(包括 <html><head> 或者空格)调用本函数。

一旦设置 Cookie 后,下次打开页面时可以使用 $_COOKIE 读取。Cookie 值同样也存在于 $_REQUEST

参数

» RFC 6265 提供了 setcookie() 每个参数的参考标准。

name

Cookie 名称。

value

Cookie 值。这个值储存于用户的电脑里,请勿储存敏感信息。比如 name'cookiename',可通过 $_COOKIE['cookiename'] 获取它的值。

expires_or_options

Cookie 的过期时间。这是 Unix 时间戳,即纪元以来的秒数。一种设置此值的方式是将 cookie 过期前的秒数与调用 time() 的结果相加。例如,time()+60*60*24*30 就是设置 Cookie 30 天后过期。还有一种选择就是使用 mktime() 函数。如果设置为 0 或者忽略,Cookie 会在会话结束时过期(关掉浏览器时)。

注意:

可能会注意到,expires_or_options 使用 Unix 时间戳而非 Wdy, DD-Mon-YYYY HH:MM:SS GMT 这样的日期格式,是因为 PHP 内部作了转换。

path

Cookie 有效的服务器路径。设置成 '/' 时,Cookie 对整个域名 domain 有效。如果设置成 '/foo/',Cookie 仅仅对 domain/foo/ 目录及其子目录有效(比如 /foo/bar/)。默认值是设置 Cookie 时的当前目录。

domain

Cookie 的有效域名/子域名。设置成子域名(例如 'www.example.com'),会使 Cookie 对这个子域名和它的三级域名有效(例如 w2.www.example.com)。要让 Cookie 对整个域名有效(包括它的全部子域名),只要设置成域名就可以了(这个示例里是 'example.com')。

旧版浏览器仍然在使用废弃的 » RFC 2109,需要一个前置的点 . 来匹配所有子域名。

secure

设置这个 Cookie 是否仅仅通过安全的 HTTPS 连接传给客户端。设置成 true 时,只有安全连接存在时才会设置 Cookie。如果是在服务器端处理这个需求,程序员需要仅仅在安全连接上发送此类 Cookie(通过 $_SERVER["HTTPS"] 判断)。

httponly

设置成 true,Cookie 仅可通过 HTTP 协议访问。这意思就是 Cookie 无法通过类似 JavaScript 这样的脚本语言访问。要有效减少 XSS 攻击时的身份窃取行为,可建议用此设置(虽然不是所有浏览器都支持),不过这个说法经常有争议。 truefalse

options

关联 array,可能会存在以下键 expirespathdomainsecurehttponlysamesite。如果存在其它的键,会生成 E_WARNING 级别的错误。这些值的含义跟同名参数的描述相同。samesite 元素的值应该是 NoneLaxStrict。如果没有指定任何允许的选项,它们的默认值与显式参数的默认值相同。如果省略 samesite 元素,则不设置 SameSite cookie 属性。

注意:

要设置一个包含不在列出的关键字中的属性的 Cookie,使用 header()

返回值

如果在调用本函数以前就产生了输出,setcookie() 会失败并返回 false。如果 setcookie() 成功运行,返回 true。当然,它的意思并非用户是否已接受 Cookie。

更新日志

版本 说明
8.2.0 Cookie 的日期格式现在为 'D, d M Y H:i:s \G\M\T'; 以前是 'D, d-M-Y H:i:s T'
7.3.0 新增对替代签名 options 数组的支持。此签名还支持 SameSite cookie 属性的设置。

示例

以下示例展示了一些发送 Cookie 的方法。

示例 #1 setcookie() 发送示例

<?php
$value
= 'something from somewhere';

setcookie("TestCookie", $value);
setcookie("TestCookie", $value, time()+3600); /* 1 小时过期 */
setcookie("TestCookie", $value, time()+3600, "/~rasmus/", "example.com", 1);
?>

注意:在发送 Cookie 时,值的部分会被自动 urlencode 编码。收到 Cookie 时,会自动解码,并赋值到可变的 Cookie 名称上。如果不想被编码,可以使用 setrawcookie() 代替。在脚本里查看我们的测试 Cookie 的内容,使用下面的一个示例:

<?php
// 打印一个单独的 Cookie
echo $_COOKIE["TestCookie"];

// debug/test 查看所有 Cookie 的另一种方式
print_r($_COOKIE);
?>

示例 #2 setcookie() 删除示例

要删除一个 Cookie,应该设置过期时间为过去,以触发浏览器的删除机制。下面的示例展示了如何删除上个示例里的 Cookie:

<?php
// 设置过期时间为一个小时前
setcookie("TestCookie", "", time() - 3600);
setcookie("TestCookie", "", time() - 3600, "/~rasmus/", "example.com", 1);
?>

示例 #3 setcookie() 和数组

通过带 array 标记的 Cookie 名称,也可以把 Cookie 设置成数组。如果有数组元素,可以把它放进 Cookie 里;脚本接收到时,Cookie 名称里的值会是一个数组:

<?php
// 设置 Cookie
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
setcookie("cookie[one]", "cookieone");

// 网页刷新后,打印出以下内容
if (isset($_COOKIE['cookie'])) {
foreach (
$_COOKIE['cookie'] as $name => $value) {
$name = htmlspecialchars($name);
$value = htmlspecialchars($value);
echo
"$name : $value <br />\n";
}
}
?>

以上示例会输出:

three : cookiethree
two : cookietwo
one : cookieone

注意: 使用 [] 分隔符作为 cookie 名称的一部分不符合 RFC 6265 第 4 节。但根据 RFC 6265 第 5 节应该由 user agent 支持。

注释

注意:

要在调用本函数前输出内容,可以使用输出缓冲,让输出的内容在服务器里缓冲起来,直至真正发送给浏览器。可在脚本里调用 ob_start()ob_end_flush(),或设置 output_buffering php.ini 或服务器配置文件里的配置指令。

注意避坑:

  • 在页面(Cookie 可见的页面)下次刷新前,Cookie 不会生效。 测试 Cookie 是否已经成功设置,需要在下次页面加载时、Cookie 过期前检测。 过期时间是通过 expires_or_options 参数设置的。 直接调用 print_r($_COOKIE); 调试检测 Cookie 是个很好的方式。
  • 为同一个参数再次设置 Cookie 前,必须先把它删掉。 如果参数的值是空 string,并且其他参数和上次调用 setcookie 仍旧一样, 则指定的名称会被远程客户端删除。 内部的实现是:将值设置成 'deleted',且过去的过期时间。
  • 因为设置值成 false 会导致 Cookie 被删除,所以要避免使用布尔值。 代替方式:0false1true
  • Cookie 名称可以设置成数组名称,PHP 脚本里会是数组, 但用户系统里储存的是单独分开的 Cookie。 可以考虑使用 explode() 为一个 Cookie 设置多个名称和值。 不建议将 serialize() 用于此处,因为它会导致安全漏洞。

多次调用 setcookie() 会按调用顺序执行。

参见