Laravel Session 默认可用,但 session('key') 取不到值或 put() 写不进数据,主因是 SESSION_DRIVER 配置不匹配(如 .env 与 config/session.php 不一致)、file 驱动目录无写权限、redis/database 驱动未正确配置或迁移、API 路由缺失 web 中间件,以及误用 $_SESSION 或 session([]) 全量替换导致加密、GC 和 flash 机制失效。

Session 在 Laravel 里默认就可用,但如果你调用 session('key') 拿不到值、$request->session()->put('key', 'value') 写不进数据,大概率不是代码写错了,而是驱动没配对或中间件没加载。
SESSION_DRIVER 配不匹配是头号故障点
本地开发用 file 驱动(默认),但部署到容器或无写入权限的服务器时,storage/framework/sessions 目录可能不可写——这时 session 表面“没报错”,实则每次请求都新建一个空会话,数据根本存不住。
- 检查
.env中的SESSION_DRIVER=redis是否和config/session.php里的'driver' => env('SESSION_DRIVER', 'file')一致 -
redis驱动要求 PHP 已启用phpredis扩展,且REDIS_HOST可连;database驱动必须先运行php artisan session:table&&php artisan migrate -
array驱动只在 PHPUnit 测试中安全,它不持久化,每次请求重置——上线环境留着等于关掉 session
API 路由没 session?是因为缺 'web' 中间件
Laravel 的 API 路由组默认不加载 StartSession 中间件,所以即使你写了 session('user_id'),也永远是空的——这不是 bug,是设计。
- 需要 session 的 API 接口(比如调试用、或混合式前端),必须显式加中间件:
->middleware('web') - 检查
app/Http/Kernel.php中$middlewareGroups['web'],确保\Illuminate\Session\Middleware\StartSession::class在你自定义中间件之前 - 如果某个中间件提前
throw异常或返回响应(比如权限拦截),StartSession的写入逻辑就被跳过了,session 不会落盘
session()->put() 和 session([]) 语义完全不同
两者都能存数据,但行为差异极大,误用会导致 flash 数据、CSRF token 全丢。
-
session()->put('user.id', 123)安全,只改嵌套路径,不影响user.name或其他顶层 key -
session(['user.id' => 123])危险,会把整个$_SESSION替换为只有['user.id' => 123]的数组,原有 flash 数据、CSRF token 全丢 - 存普通数据推荐用
session()->put();全量替换只在明确需要清空旧键时才用session([])
别直接操作 $_SESSION,否则加密和 GC 全失效
手动改 $_SESSION['key'] = 'value' 看似能用,但会绕过 Laravel 的序列化、加密、垃圾回收逻辑,导致 flash 数据丢失、跨请求取不到值,甚至触发 Serialization of closure is not allowed 错误。
- 存:用
session(['key' => 'value'])或$request->session()->put('key', 'value') - 取:用
session('key', 'default')(带默认值防 null)、$request->session()->get('key') - 删:用
session()->forget('key'),不是unset($_SESSION['key']) - 闪存:必须用
session()->flash('msg', 'done'),put + forget模拟不了它的“仅下一次有效”语义
真正容易被忽略的是中间件顺序和驱动配置的耦合性——比如你改了 SESSION_DRIVER,却忘了清配置缓存(php artisan config:clear),或者 Redis prefix 配错导致多应用串号,这些都不会报错,只会静默失效。


















