ThinkPHP 5.1 的 session.driver 必须配置在 config/app.php 的 session 子数组中,而非 config/session.php;TP6 需安装 think-session 扩展才支持非 file 驱动,且 Redis 参数须以数组形式传入 session.redis_config。

ThinkPHP 5.1 的 session.driver 配置位置和生效逻辑
TP5.1 默认使用文件驱动,但配置不写在 config/session.php 里就无效——它实际读取的是 config/app.php 中的 session 子数组。很多人改了 session.php 却没效果,就是因为框架根本没加载那个文件。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
-
session.driver必须放在config/app.php的'session' => [...]里,不是单独的配置文件 - Redis 驱动需额外安装
ext-redis,且session.redis.host等参数必须显式配置,不能依赖环境变量自动填充 - 如果启用了多应用模式(
app_multi),session.name建议加前缀,否则不同应用会互相覆盖 session_id - 开启
session.auto_start后,控制器里再调session()可能触发「headers already sent」错误,建议统一用中间件控制启动时机
ThinkPHP 6.x 的 think-session 扩展与原生驱动切换
TP6 把 Session 拆成独立扩展 think-session,默认不内置 Redis/Memcached 驱动。直接写 driver => 'redis' 会报错:Driver [redis] not supported.
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 先执行
composer require topthink/think-session,否则任何非 file 驱动都不可用 - Redis 连接参数必须通过
session.redis_config传入完整数组,不支持扁平化写法(比如不能只写host,得写['host' => '127.0.0.1', 'port' => 6379]) - TP6.3+ 开始支持
cache驱动复用缓存配置,但要注意:如果缓存用的是redis,Session 仍需单独配连接池参数,不会自动继承cache.redis配置 - 使用 Swoole 或 Hyperf 兼容模式时,
file驱动可能因多进程写同一目录出错,必须指定session.path到每个 worker 独立路径
Session ID 被重置或跨请求丢失的典型原因
不是配置错,而是运行时行为踩坑。最常见的是:响应头被提前输出、域名/路径不一致、HTTPS 混合访问。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 检查是否有
echo、var_dump或 BOM 字符在index.php或配置文件开头,导致 headers 发送失败 - 前端发请求时 Host 是
localhost,后端 Nginx 配置了server_name example.com,会导致 Cookie 的Domain不匹配而被浏览器丢弃 - 开发环境 HTTP + 生产环境 HTTPS 时,
session.cookie_secure必须动态判断:TP6 可用Env::get('app_debug') ? false : true控制 - TP5.1 在 CLI 模式下默认禁用 Session,但单元测试里调用
session()不报错,只是数据不持久——这不是 bug,是设计如此
自定义 Session 驱动时 read() 和 write() 的关键约束
自己写 Redis 或数据库驱动时,read() 返回空字符串表示“未找到”,返回 null 会导致框架内部判为异常并清空 session;write() 必须返回布尔值,且不能抛异常(TP 会静默吞掉)。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
-
read($id)中若查不到记录,必须return '',不能return false或throw new Exception() -
write($id, $data)的$data是已序列化的字符串(TP 自动处理serialize()),不要二次编码 - TP6 的驱动接口要求实现
gc($max_lifetime),但实际很少调用;如果你用的是 Redis 的过期键,可以留空或直接return true - 数据库驱动中,
id字段必须设为唯一索引,否则并发写入可能产生重复记录,造成后续read()返回脏数据


















