【问题标题】:Loses Auth :: user () when declaring an Oberserver in AppServiceProvider在 AppServiceProvider 中声明 Observer 时丢失 Auth :: user ()
【发布时间】:2020-03-28 11:44:16
【问题描述】:

我正在尝试在我的一个模型中使用本地范围,但为此我需要检查用户权限,因此我尝试通过 Auth::user() 获取经过身份验证的用户。

但它给了我一个空值,因为我为这个模型声明了一个观察者,如果我评论观察者的声明,Auth::user() 方法给我一个经过身份验证的用户。

有一个正确的方法或地方来声明观察者,并且在模型中我可以获得经过身份验证的用户,因为我需要使用观察者并在引导方法中获取经过身份验证的用户?

Laravel 框架 6.5.2

AppServiceProvider 不要在模型中进行身份验证

 /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Conciliador::observe(ConciliadorObserver::class);
        Proposta::observe(PropostaObserver::class);

    }

AppServiceProvider 在模型中工作验证

 /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //Conciliador::observe(ConciliadorObserver::class);
        //Proposta::observe(PropostaObserver::class);

    }

AppServiceProvider中声明Observer时模型没有用户登录

 /**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();
        $user = Auth::user();
        dd($user); // null if Observer is declared in AppServiceProvider
        if($user && $user->tipo == 'admin-gerenciador'){
            $conciliadores = $user->conciliadores->pluck('id')->toArray();
            static::addGlobalScope('Conciliadores', function (Builder $builder) {
                $builder->whereIn('id',$conciliadores);
            });
        }
    }

【问题讨论】:

  • 你使用的是哪个版本的 Laravel?
  • Laravel 框架 6.5.2 @ChinLeung

标签: laravel eloquent


【解决方案1】:
  • 不要在任何地方打电话给Auth::user()。它可能会触发身份验证副作用。强烈建议仅在控制器和中间件中执行此操作。
  • 但如果您提前通过Auth::hasUser()查看,您可以放心拨打Auth::user();它会检查用户是否已经通过身份验证。

所以你的代码是这样的:

/**
 * The "booting" method of the model.
 */
protected static function boot(): void
{
    static::addGlobalScope('Conciliadores', function (Builder $query) {
        if (Auth::hasUser() && Auth::user()->tipo === 'admin-gerenciador') {
            $query->whereKey(Auth::user()->conciliadores->modelKeys());
        }
    });
}

这是非常简单的解决方案。甚至不需要中间件。

编辑

此范围始终可用,但实际上仅在用户已通过身份验证时才应用条件

【讨论】:

  • Thankyou @mpyw,但是在代码通过 AppServiceProvider 上的引导方法传递并拥有登录用户后,我需要将范围应用于模型。我该怎么做?
  • 您是否更喜欢“仅在身份验证后应用的每个用户的全局范围”而不是“始终应用仅适用于经过身份验证的用户的全局范围”?我认为它们的行为方式完全相同,但你敢选择复杂的实现吗?
【解决方案2】:

您不应该在模型的启动方法中这样做。 boot 方法只为模型调用一次,而不是为每个模型实例调用。第一次使用模型时,boot 会被调用,这就是您在服务提供者中为它添加观察者的情况;这将是在请求被分派到路由并通过中间件堆栈之前的方式。 (此时没有会话,因此没有经过身份验证的用户。)

您可能希望通过中间件将全局范围添加到模型中。

【讨论】:

  • 你能给我一个例子如何使用中间件做到这一点吗? @lagbox
猜你喜欢
  • 2019-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 1970-01-01
  • 2018-04-08
相关资源
最近更新 更多