中间件中可直接用Cookie::get()读取Cookie,无需额外use或初始化,前提是config/cookie.php中'setcookie'=>true(默认开启),且domain、secure等配置与当前请求匹配;读不到时优先确认Cookie是否已由上一次响应正确写入并随本次请求发送。

中间件里直接调用 Cookie::get() 就能读取
ThinkPHP 6 的中间件默认已加载 Cookie 组件,不需要额外 use 或初始化。只要配置没禁用,Cookie::get('key') 在中间件中和控制器里行为一致。
常见错误是误以为中间件不能访问 Cookie —— 实际上它比控制器更早执行,只要响应头还没发出去,读取完全没问题。
- 确保
config/cookie.php中'setcookie' => true(默认开启),否则底层不调用setcookie(),但读取不受影响 - 如果启用了
auto_encrypt,Cookie::get()会自动解密,无需手动处理 - 读不到值时,先确认 Cookie 是否真被写入:在控制器里用
Cookie::set('test', 'ok')+Cookie::get('test')对照测试
cookie() 助手函数在中间件中可用,但有前提
cookie('key') 这类助手函数依赖全局函数定义,TP6 默认启用,但如果你项目里禁用了助手函数(比如通过 app.use_helper = false 配置),就会报 Undefined function cookie() 错误。
安全起见,中间件中建议统一用门面类 Cookie::get(),避免环境差异导致失败。
立即学习“PHP免费学习笔记(深入)”;
- 不推荐在中间件中混用
cookie('key')和Cookie::get('key'),容易因配置变更突然失效 - 若坚持用助手函数,需确认
think\helper\Cookie类已加载,且未被覆盖或重定义 - 注意前缀:如果配置了
'prefix' => 'tp6_',Cookie::get('token')实际读的是浏览器里的tp6_token
跨子域或 HTTPS 环境下读不到?重点检查 domain 和 secure
中间件里读取失败,十次有七次是 Cookie 根本没发到当前请求的域名或协议下。
比如前端请求是 https://api.example.com,但 Cookie 的 domain 配置成 'domain' => 'example.com' 且 'secure' => true,而你本地调试用的是 http://localhost:8000,那浏览器压根不会带上这个 Cookie,中间件自然读不到。
- 开发时临时关闭安全限制:在中间件里显式传参绕过配置,如
Cookie::get('token', ['domain' => '', 'secure' => false]) - 生产环境必须匹配:确保
config/cookie.php中的domain值以.开头(如'.example.com')才能被子域共享 -
httponly => true不影响服务端读取,只禁止 JS 访问,这点常被误解
中间件中读取后做鉴权,别忽略 Cookie 生命周期校验
单纯读到值不等于有效。比如你用 Cookie::get('auth_token') 拿到字符串,但没验证是否过期、是否被篡改、是否绑定 IP/User-Agent,就放行请求,会有安全隐患。
TP6 的 Cookie::get() 返回 null 仅表示键不存在或已过期(底层基于 time() > expire_time 判断),但不校验内容合法性。
- 加密 Cookie 被篡改后,
Cookie::get()会直接返回null(不是原始值),这是框架自动做的完整性校验 - 建议在中间件中补充业务逻辑:比如检查 token 是否在黑名单、是否与当前用户 session 匹配、时间戳是否在合理窗口内
- 不要把敏感字段(如 user_id、role)全放 Cookie 里,哪怕加密了——服务端应以 session 或数据库为准
真正容易被忽略的点是:中间件执行时机早于控制器,但 Cookie 的写入可能发生在后续响应阶段。也就是说,你在中间件里读不到「本请求中刚 set 的 Cookie」,因为浏览器还没收到它;你读的永远是「上一次响应写入、本次请求带过来的」那个值。



















