Laravel 9会话存储用户对象不实时同步数据库数据问题
Laravel 9登录系统Session数据不实时更新问题
我正在使用Laravel 9开发登录系统,在登录流程的下一步中,添加了用于验证用户手机号码的输入框:
<input type="text" name="userinput" class="form-control" id="phone">
在控制器中,通过手机号查询用户并将用户对象存入Session:
$findUser = User::where('usr_mobile_phone',$request->userinput)->first(); if($findUser){ Session::put('userData',$findUser); return redirect()->route('auth.login.next'); }else{ return redirect()->back()->withErrors('No results!'); }
对应auth.login.next路由的控制器方法中,从Session取出用户对象并传递到视图:
public function loginNext() { $user = Session::get('userData'); if(Session::has('nextStep') && Session::get('nextStep') == 1){ return view('frontend.auth.next', compact('user')); }else{ abort(404); } }
在next.blade.php视图中,通过判断$user->usr_password_hash是否为空来显示密码登录按钮:
@if(!empty($user->usr_password_hash)) // Show button login with password @endif
问题
功能正常但存在异常:停留在当前页面时,通过phpMyAdmin手动将该用户的usr_password_hash设为NULL,页面仍显示密码登录按钮,而控制器中用dd($user)能获取到更新后的信息,请问原因是什么?
原因及解决办法
核心原因
Session中存储的是用户对象的静态快照副本,不会自动同步数据库的实时变更:
- 第一次通过手机号查询用户时,Laravel会将当时数据库里的用户数据(包含非空的
usr_password_hash)序列化后存入Session; - 手动修改数据库字段后,Session内的旧数据并未被更新;
- 刷新页面时,控制器直接从Session取出旧的用户对象传递给视图,因此视图判断逻辑仍基于旧数据显示按钮;
- 你提到控制器用
dd($user)能拿到更新数据,大概率是测试时重新执行了手机号查询流程(比如重新提交手机号),此时Laravel会重新查询数据库,将最新用户数据存入Session覆盖旧数据。
解决办法
如果需要实时获取用户最新数据,有两种常用方案:
- 重新查询数据库:从Session中取出用户ID,在
loginNext方法里重新拉取最新数据:
public function loginNext() { $userData = Session::get('userData'); if(Session::has('nextStep') && Session::get('nextStep') == 1 && $userData){ // 重新查询数据库获取最新用户信息 $user = User::find($userData->id); return view('frontend.auth.next', compact('user')); }else{ abort(404); } }
- 监听模型更新事件:如果是业务操作导致用户数据变更,可以通过Laravel的模型事件监听(如
updated事件),在用户数据更新时主动同步Session内的用户信息,但这种方式无法覆盖手动修改数据库的场景。
内容的提问来源于stack exchange,提问作者Pouya Vaghefi
相关产品推荐
相关产品推荐

