ThinkPHP6中Session必须启用SessionInit中间件、正确配置config/session.php参数,并禁用原生$_SESSION和session_start();否则Session::get()返回null或报错。

ThinkPHP 的 Session 不是“调用就能用”,必须确认中间件已启用、配置已生效、且没混用原生 $_SESSION 或 session_start() —— 否则大概率读不到值或报错。
TP6 必须启用 SessionInit 中间件
TP6 默认不自动初始化 Session,哪怕你配了 config/session.php,没注册中间件就等于没开锁。
- 检查
app/middleware.php是否包含\think\middleware\SessionInit::class - 如果用了多应用或子域名路由,需确认该中间件在对应应用的中间件栈中生效
- 禁用此中间件后,
Session::get()会返回null,但不会报错,容易误判为“数据丢了”
config/session.php 关键参数含义与常见陷阱
文件里写的不是“建议值”,而是直接影响 session 文件名、过期逻辑和跨域行为的实际开关。
-
type:设为'file'时,path必须可写(如runtime/session),否则首次写入就静默失败 -
prefix:默认是'think_',但如果你在多个 TP 应用共用同一域名,必须改不同前缀,否则 A 应用删了 B 应用的 session -
expire单位是**分钟**(不是秒),设1440= 24 小时;但实际失效还受 PHP 的session.gc_maxlifetime限制,后者若设得更小,以它为准 -
name改动后,浏览器 Cookie 名就变,老用户会“登录态丢失”,上线前需评估是否兼容
think\facade\Session 的实际操作边界
别把 Session 当成普通数组用,它的作用域、生命周期和取值逻辑都有隐含规则。
立即学习“PHP免费学习笔记(深入)”;
-
Session::set('user.id', 1001)是合法的,支持点号嵌套赋值;但Session::get('user')只能取到整个user数组,不能取user.id的父级 -
Session::get('name', 'default')第二个参数是“不存在时的 fallback”,不是“默认值写入”,不会触发 set -
Session::pull('flash')是一次性读取+删除,适合表单提交后的提示消息;重复调用第二次返回null - 绝对不要在中间件、事件或命令行任务里依赖
Session::get()—— CLI 环境无 HTTP 上下文,Session 根本不启动
为什么 $_SESSION 读不到、session_start() 报错
TP6 明确禁用原生 PHP Session 函数,框架自己接管了底层 handler。混用会导致状态错乱。
- 看到
Cannot send session cache limiter错误?基本是某处提前调了session_start(),而 TP6 的SessionInit中间件又尝试再启一次 -
$_SESSION始终为空,是因为 TP6 的 Session 数据存在自定义存储(如文件/Redis)里,不绑定 PHP 原生 superglobal - 调试时想看原始数据?直接查
runtime/session/sess_*文件(file 驱动)或 Redis key(redis 驱动),别盯$_SESSION
最常被忽略的一点:Session 的「自动启动」只对 HTTP 请求有效,且依赖中间件顺序;一旦加了自定义中间件(比如权限校验),它必须放在 SessionInit 之后,否则 Session::get() 在校验逻辑里永远拿不到值。



















