setcookie()必须在任何输出前调用,否则因HTTP响应头已发送而报错;$_COOKIE是请求初始快照,不实时更新;删除Cookie需匹配原path/domain参数;敏感数据不应明文存入Cookie。

setcookie() 必须在任何输出之前调用
浏览器收到 HTTP 响应头才能写入 Cookie,而 setcookie() 本质就是向响应头插入 Set-Cookie 字段。一旦有哪怕一个空格、换行或 <html> 被 echo/print 输出,PHP 就会报 Warning: Cannot modify header information - headers already sent。
常见踩坑点:
- 文件开头存在 UTF-8 BOM(尤其 Windows 编辑器保存时默认带 BOM)
-
echo、print、var_dump等调试语句漏删 - 配置文件末尾有多余空白行
- 使用
include或require引入的文件含不可见字符
临时绕过办法是启用输出缓冲:ob_start() 放在脚本最开头,但不推荐长期依赖——它掩盖了输出时机混乱的问题。
$_COOKIE 是只读快照,不能直接修改
PHP 在请求开始时把所有客户端发来的 Cookie 解析进 $_COOKIE 数组,但它只是初始副本,改它不会触发浏览器更新,也不会影响后续 setcookie() 行为。
立即学习“PHP免费学习笔记(深入)”;
正确做法始终是:读用 $_COOKIE['key'],写用 setcookie('key', $value, ...)。
容易混淆的场景:
- 想“更新”已存在的 Cookie,却只改了
$_COOKIE['key'] = 'new'—— 没用,浏览器根本收不到指令 - 在同一个请求里先读
$_COOKIE,再setcookie(),误以为下次读就是新值 —— 实际上新值要等下一次请求才出现在$_COOKIE中 - 用
unset($_COOKIE['key'])试图删除 —— 不生效,必须调用setcookie('key', '', time()-3600)
路径(path)和域名(domain)设错会导致 Cookie 不可见
Cookie 的作用域由 path 和 domain 共同决定。设错后,浏览器要么不发,要么发错地方,导致 PHP 读不到。
典型错误配置:
-
setcookie('token', 'abc', 0, '/admin')→ 只在/admin/xxx下有效,主站首页访问不到 -
setcookie('user', '123', 0, '/', 'www.example.com')→ 仅限 www 子域,根域example.com或其他子域(如api.example.com)无法读取 -
domain值以点开头(如'.example.com')才允许子域共享;不加点则严格匹配
调试建议:Chrome DevTools → Application → Cookies,确认当前页面 URL 对应的 Cookie 列表是否包含你设置的项,重点核对 Path 和 Domain 字段。
敏感数据别放 Cookie,httponly 和 secure 不是万能补丁
Cookie 天然暴露在 HTTP 请求中,即使设了 httponly=true(防 XSS 读取)和 secure=true(仅 HTTPS 传输),仍可能被中间人劫持、被恶意服务端伪造、或因用户设备中毒被窃取。
真正该放 Cookie 的只有:会话 ID(配合 Session)、免登录 Token(短期+签名校验)、UI 偏好等低风险字段。
绝对禁止的:
- 明文密码、身份证号、银行卡号
- 未加密的 JWT payload(除非签名强且有效期极短)
- 任何可直接用于 API 调用的长期密钥
如果业务真需要客户端存凭证,优先走 HttpOnly + Secure + SameSite=Strict 组合,并在服务端做二次校验(如绑定 IP、User-Agent 指纹)。但这仍是权衡,不是银弹。



















