$_COOKIE是请求开始时由PHP内核自动从HTTP请求头解析的只读快照,不实时更新;setcookie()必须在任何输出前调用,因其本质是向响应头写入Set-Cookie字段,受HTTP协议头体顺序限制。

Cookie数据从浏览器到$_COOKIE的映射过程
PHP不是“读取硬盘上的cookie文件”,而是依赖Web服务器(如Apache或Nginx)在请求到达时,把HTTP请求头中的Cookie字段内容解析后,注入到$_COOKIE数组里。这个动作发生在脚本执行前,由PHP内核自动完成——你写的任何代码都接触不到原始HTTP头,只看到已解码、已过滤的键值对。
常见错误现象:修改$_COOKIE['user_id'] = 'abc'完全无效,页面刷新后还是旧值。因为$_COOKIE是只读快照,不是客户端存储代理。
- 必须用
setcookie()或setrawcookie()才能真正写入客户端 -
$_COOKIE里的值只反映本次请求携带的Cookie,不包含刚用setcookie()设置但尚未返回给浏览器的内容 - 如果
variables_order配置中没包含C(比如被改成GPCS),$_COOKIE会为空,即使请求头里有Cookie字段
setcookie()为什么必须在输出之前调用
本质是HTTP协议限制:Set-Cookie属于响应头(Response Header),而一旦开始输出HTML、空格、BOM甚至换行,PHP就认为响应体(body)已启动,无法再写头部。这不是PHP的bug,是所有遵循HTTP/1.1规范的服务器共同行为。
容易踩的坑:
立即学习“PHP免费学习笔记(深入)”;
-
<?php echo ""; setcookie("a", "b"); ?>—— 开头的echo导致Header already sent错误 - UTF-8 BOM头(\xEF\xBB\xBF)被当成输出,常出现在编辑器保存时悄悄加入
- 使用
ob_start()可以缓冲输出,延迟真实发送,但只是绕过限制,不改变底层逻辑
Cookie路径(path)和域名(domain)如何影响可见性
这两个参数直接决定浏览器是否在某次请求中把Cookie发给服务器。它们不是“建议”,而是强制匹配规则。
典型场景:
- 设
setcookie("cart", "[]", 0, "/shop/"),那么只有访问/shop/或其子路径(如/shop/cart.php)时,该Cookie才会随请求发出 - 设
domain=".example.com",则www.example.com和api.example.com都能读取;但设成"www.example.com"则api.example.com收不到 - 省略
domain参数时,浏览器默认只匹配当前主机名,不带点号前缀,所以example.com和www.example.com被视为不同域
安全标志(secure / httponly)的实际效果差异
secure和httponly不是装饰性参数,它们对应HTTP响应头里的两个独立标志位,浏览器按RFC 6265严格执行。
关键区别:
-
secure=true→ 只在HTTPS连接下发送Cookie,HTTP请求中彻底不携带(哪怕页面是HTTPS加载,但AJAX请求走HTTP,也不会发) -
httponly=true→ 浏览器禁止JavaScript通过document.cookie读写该Cookie,但服务端仍可通过$_COOKIE正常读取 - 两者都为
true是最常见做法,尤其对PHPSESSID或登录态Token
注意:httponly不能防止XSS窃取Cookie(因为攻击者可发起带Cookie的请求),但它能阻止直接读取值——这是防御纵深里的基础一环。



















