ThinkPHP中Session失效主因是底层存储未生效:Linux下session.save_path目录权限不足(需1733且属主匹配)、自定义驱动时type与path/host配置不匹配、或php-fpm开启session.auto_start导致重复初始化。

Session 在 ThinkPHP 中突然失效的典型表现
页面跳转后 session() 读不到之前存的数据,或者每次刷新都生成新 PHPSESSID;用 var_dump(session_id()) 发现 ID 频繁变化,但没报错——这不是代码写错了,大概率是底层存储没接住。
Linux 下 session.save_path 目录权限不对是最常见原因
ThinkPHP 默认用 PHP 原生 file 驱动存 session,实际路径由 session.save_path 决定(不是项目里的 runtime/session)。Web 服务器(如 nginx + php-fpm)是以 www-data 或 nginx 用户运行的,如果该目录属主是 root 或权限为 755,PHP 就写不进去。
- 查当前配置:
php -i | grep session.save_path,确认真实路径(比如/var/lib/php/sessions) - 检查目录权限:
ls -ld /var/lib/php/sessions,必须是drwxrwxrwt(末位t表示 sticky bit,常见于系统 session 目录) - 若权限不足,执行:
sudo chmod 1733 /var/lib/php/sessions(1733=rwxrwxrwt),再sudo chown root:www-data /var/lib/php/sessions - 别直接改项目
runtime/session权限——ThinkPHP 的 file 驱动默认不走这里,除非你显式配置了session.type = file且session.save_path指向它
ThinkPHP 自定义 session 驱动时 save_path 和 type 必须匹配
在 config/session.php 里改了 'type' => 'file',却忘了同步设 'path',或者设了 'type' => 'redis' 但 'host' 写错,都会静默退化成内存 session(请求一结束就丢)。
-
'type' => 'file'时,'path'必须是绝对路径,且 Web 进程有写权限(例如/home/www/myapp/runtime/session) -
'type' => 'redis'时,确保ext-redis已安装,'host'、'port'、'password'全对,且 Redis 服务在监听(redis-cli -h 127.0.0.1 ping要返回PONG) - 别信文档里“自动检测”的说法:ThinkPHP 不会帮你校验 Redis 连通性,连不上就 fallback 到
php://input,结果就是 session 看似启动了,实则没存
PHP-FPM 的 session.auto_start 开启会导致冲突
如果 php.ini 或 www.conf 里设置了 session.auto_start = 1,PHP 会在脚本执行前自动调用 session_start(),而 ThinkPHP 又在 SessionInit 中再调一次——两次 start 会触发警告 session_start(): Trying to destroy uninitialized session,部分版本下直接让 session 数据不可写。
立即学习“PHP免费学习笔记(深入)”;
- 查是否开启:
php -i | grep session.auto_start,输出On就得关 - 在
php.ini中设为session.auto_start = 0,或在 FPM pool 配置里加php_flag[session.auto_start] = off - 改完重启
php-fpm,别只 reload,有些版本 reload 不生效
session 的问题从来不在 set 和 get,而在初始化那一刻有没有真正落地。路径权限、驱动配置、PHP 层开关,三者只要一个没对齐,数据就停在内存里出不去。调试时先盯死 session_id() 是否稳定,再查 session_save_path() 返回值和对应目录状态,比翻业务代码快得多。



















