Laravel 5.8:如何在全局范围的 apply 方法中解析 auth()->user()?

Mat*_*cki 8 php ioc-container inversion-of-control laravel laravel-5.8

仅当经过身份验证的用户的角色等于某些内容时,我才需要应用特定的全局范围。因此,具有特定角色的用户将只能对给定的记录子集执行查询。

我可以轻松处理 User 模型(当前登录的用户),但不能处理范围内的 apply 方法。

https://github.com/laravel/framework/issues/22316#issuecomment-349548374

在 auth 中间件运行之前,范围构造函数很早就执行了。在 apply 方法中解析用户,而不是在构造函数中。

好的,所以我在apply方法中:

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class UserScopeForSalesContactAdmin implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        dd('within apply', auth()->user());
        dd(auth()->user()); // won't work

        $builder->where('foo', '=', 'something from currently logged in user');
    }
}
Run Code Online (Sandbox Code Playgroud)

显然第二个dd给出:

达到“512”的最大函数嵌套级别,中止!

如何解决这个问题?我想我应该通过调用 IOC 容器,app()->make()然后呢?

感谢您的任何提示。

编辑:我想我明白是什么导致了无限循环(https://github.com/laravel/framework/issues/26113)但我仍然需要找到一种获得用户的最佳方法......

mpy*_*pyw 9

您正在寻找的方法正是Auth::hasUser(). 该方法是通过我的 PR 在 Laravel 5.6 中添加的。

[5.6] 添加确定当前用户是否已通过身份验证而不会触发 mpyw 的副作用的能力 · 拉取请求 #24518 · laravel/框架

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class UserScopeForSalesContactAdmin implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        if (Auth::hasUser() && Auth::user()->role === 'something') {
            $builder->where('foo', '=', 'something from currently logged in user');
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

只需致电Auth::hasUser()以防止Auth::user()造成副作用。


mrh*_*rhn 0

这里的问题是您正在为 User 定义一个范围,在使用 Auth::user() 检索用户时,它将在解决第一个方法调用之前再次利用该范围,并且从那里我们有一个 StackOverflow。我认为有一个聪明的方法,覆盖守卫,并将用户模型保存在您可以从那里取出的类上,但我也不喜欢使用内置Laravel功能进行调整。

一个简单的方法可能是利用 Auth::id 并使用 DB::table 获取所需的信息,它不太漂亮,但我认为这是解决问题的直接方法。

public function apply(Builder $builder, Model $model)
{
    // this will not trigger the scope when you fetch it out again, and avoiding the stackoverflow
    $user = DB::table('users')->where('id', Auth::id())->get()->first();

    $builder->where('foo', '=', $user['the_answer_to_life']);
}
Run Code Online (Sandbox Code Playgroud)