session 在中间件中读不到,主因是 sessioninit 未注册或顺序错误、未调用 session::save()、误用 $_session 或 request->param()、cookie 域配置不当、或 session 驱动未显式声明。

Session 在中间件里读不到,基本就是 Session 初始化太晚,或者中间件位置错了。
SessionInit 中间件没注册或顺序不对
ThinkPHP 6/8 默认不自动启动 Session,SessionInit 必须显式注册,且必须排在所有依赖 Session 的中间件之前(比如 Lang、AuthCheck)。
- 打开
app/middleware.php,确认返回数组第一项是\think\middleware\SessionInit::class - 错误示例:
\think\middleware\Lang::class在SessionInit前面 →cookie('think_lang')和session('user_id')全为空 - 多应用模式下,每个子应用的
app/middleware.php都要单独检查,全局配置不继承 - 改完后务必执行
php think clear,否则缓存旧配置,白改
中间件里用了 session() 函数但没保存
TP6 的 Session 是延迟写入的:调用 session('key', 'val') 只是暂存内存,不触发持久化。页面跳转或刷新后就丢。
- 写入后必须加一行
\think\facade\Session::save(),尤其在 Lang 或登录中间件中设置语言或用户 ID 后 - 别依赖“设了就等于存进去了”——
session('lang', 'en-us')不跟Session::save()配套,下次请求一定为空 - 如果用的是 Redis 驱动,
save()还会强制刷新连接状态,避免因连接空闲超时导致写入静默失败
读取方式不当或时机过早
不是所有 Session 访问方式都等效,也不是所有中间件阶段都能安全读取。
- 优先用
\think\facade\Session::get('key'),比全局函数session('key')更稳定,尤其在中间件生命周期早期 -
$request->param('key')不能替代 Session 读取——它合并 GET/POST,但和 Session 无关;想读 Session 就得走 Session facade - 不要在中间件 handle() 开头就硬读
$_SESSION['user_id'],PHP 原生超全局变量在 TP6 中未初始化前就是空数组,应始终通过 facade 访问 - 若需跨请求传参(如登录态),确保 Cookie domain 设置正确(
.example.com),否则子域名间 Session Cookie 根本不会发送
最常被忽略的一点:Session 驱动未显式声明。config/app.php 中的 session 配置若没写 'driver' => 'file'(或 'redis'),框架连 session_start() 都不调,你写的任何 session() 全部静默失效,还不报错。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











