Laravel 5.6中在服务提供者获取Sentinel认证用户返回null问题
解决Laravel 5.6里Sentinel在服务提供者boot方法拿不到已认证用户的问题
嘿,这个问题我之前也碰到过,核心原因其实是服务提供者的boot方法执行时机太早了!
为啥会返回null?
Laravel启动的时候,服务提供者的boot方法是在应用初始化阶段就跑起来的,这时候负责处理用户认证的中间件还没开始工作呢。Sentinel要拿到已登录用户,得靠认证中间件解析请求里的会话或者token信息,所以在boot阶段调用Sentinel::getUser(),自然拿不到用户实例,只能返回null。
给你两个靠谱的解决方案:
方案一:用视图Composer延迟获取用户
视图Composer是在视图实际渲染的时候才执行逻辑的,这时候认证中间件已经完成了用户识别,肯定能拿到正确的用户数据:
use View; use Sentinel; use Illuminate\Support\ServiceProvider; class AuxiliaryServiceProvider extends ServiceProvider { public function boot() { // 给所有视图绑定composer,*代表匹配所有视图 View::composer('*', function ($view) { $view->with('loggedUser', Sentinel::getUser() ?? null); }); } public function register() { // 这里不用改 } }
这样loggedUser变量会在每个视图渲染时动态获取当前登录用户,不仅能解决null的问题,还能保证数据是实时的。
方案二:自定义中间件来共享用户
如果你想在请求周期更早的阶段共享用户数据,可以整个中间件来做:
- 先生成中间件:
php artisan make:middleware ShareLoggedUser
- 打开生成的
app/Http/Middleware/ShareLoggedUser.php,写逻辑:
use Closure; use Sentinel; use View; class ShareLoggedUser { public function handle($request, Closure $next) { // 共享用户到所有视图 View::share('loggedUser', Sentinel::getUser() ?? null); return $next($request); } }
- 去
app/Http/Kernel.php的web中间件组里注册这个中间件,注意要放在Sentinel的认证中间件之后,不然还是拿不到用户:
protected $middlewareGroups = [ 'web' => [ // ...其他中间件 \Cartalyst\Sentinel\Laravel\Middleware\Check::class, // Sentinel的认证中间件 \App\Http\Middleware\ShareLoggedUser::class, // 你的自定义中间件 ], ];
小提醒
以后别在服务提供者的boot/register方法里直接拿请求相关的状态(比如认证用户)啦,这些方法是应用启动时执行的,和具体请求没关系,很容易出问题。视图Composer是更推荐的方式,性能更好,逻辑也更合理~
内容的提问来源于stack exchange,提问作者WillKoz
相关产品推荐
相关产品推荐

