ThinkPHP 6 改 config/session.php 不生效是因为 Session 驱动切换非纯配置行为:必须同时满足启用 redis 扩展、安装 think-session-redis 包、补全 redis 所有必填参数(host/port/select/timeout/prefix)、开启 Session 中间件,缺一即静默回退 file 驱动。

直接改 config/session.php 不生效,是因为 ThinkPHP 6 的 Session 驱动切换不是纯配置行为——缺任何一环都会静默回退到 file,且不报错。
为什么改了 type=redis 却还是走文件存储
常见现象:配置写了 'type' => 'redis',但 session()->getHandler() 返回的是 think\session\driver\File。根本原因不是配置写错,而是以下任一条件未满足:
- PHP 未启用
redis扩展(注意是ext-redis,不是predis或phpredis别名),执行php -m | grep redis必须有输出 - 未安装官方 Redis 驱动扩展:
composer require topthink/think-session-redis -
redis配置块缺失关键字段,比如漏掉'host'、'port'或'select'(TP6 不会读取redis://DSN,也不 fallback 到环境变量) -
session.cookie_httponly或session.cookie_secure与当前环境不匹配,导致 Cookie 未发送,Redis 根本没收到新 Session ID
Redis 驱动必须显式配置的参数项
TP6 的 redis 驱动不接受“默认值”逻辑,所有连接参数都需明确定义。以下字段缺一不可:
-
'host':不能填localhost或127.0.0.1(多机部署时会连错本机),应填内网可达 IP,如'10.0.1.100' -
'port':通常6379,但若 Redis 启用了 ACL(Redis 6+),密码格式为'user:pass',不是纯密码 -
'select':必须指定数据库编号(如2),不能留空或null;默认0容易被其他服务误清 -
'timeout':建议设为2,避免网络抖动导致整个请求阻塞 -
'prefix':多个 TP 应用共用 Redis 时必设,否则 key 冲突(如'admin_'和'api_')
示例最小可用配置:
立即学习“PHP免费学习笔记(深入)”;
'type' => 'redis',
'redis' => [
'host' => '10.0.1.100',
'port' => 6379,
'select' => 2,
'timeout' => 2,
'prefix' => 'admin_',
],
Session 数据存不了关联数组?先查序列化开关
TP6 默认对 Redis 存储使用 json_encode(),而 file 驱动用 serialize()。如果你从 file 切到 redis 后发现 session('user', ['name' => '张三']) 存进去取出来是 null,大概率是序列化方式不一致。
- 确认是否在配置中加了
'serialize' => 'php'(强制用serialize) - 避免存含
Closure、资源句柄或私有属性的对象——这不是驱动问题,是 PHP 原生限制 - key 名里别用点号(
.)或斜杠(/),例如'user.info'在部分驱动下会被解析为嵌套键,写入失败
分布式环境下 Session 失效的真正原因
不是 Redis 连不上,而是每台服务器各自写本地 file,用户轮询到不同机器就找不到 session —— 这是文件驱动的设计特性,不是 bug。
- 必须确保所有 Web 服务器能访问同一套 Redis 实例(或集群),且防火墙放行对应端口
- Nginx 反向代理时,务必透传 Cookie:
proxy_set_header Cookie $http_cookie; - 前端发请求带
withCredentials: true,后端 CORS 头就不能设Access-Control-Allow-Origin: *,否则浏览器拒绝携带 Cookie - CLI 环境(如命令行任务)默认不初始化 Session,别在那里测试 Redis 是否连通
最常被忽略的一点:TP6 默认不开启 Session 中间件,app/middleware.php 里必须手动加入 \think\middleware\SessionInit::class,否则整个生命周期里 session 都不会启动。



















