优雅地退出 Laravel 个范围

Gracefully exiting Laravel scopes

我有一个范围,它根据用户角色以限制方式运行,您可以将一组规则转发到限制数据库最终输出的范围。

一个真正简化的角色限制示例:

{
    "first_name": "=foo%"
}

将仅 return 条 first_namefoo% 开头的记录,这实际上意味着我已禁止具有该角色的用户查看任何不以 [= 开头的记录14=].

这种方法的问题在于,如果某人没有强加的限制,他将看到一切。我知道这是一个有效的假设,但如果没有施加限制,我想禁止一切,这样如果创建了新角色,它就没有任何权利。

目前我正在为这种情况抛出异常:

public function apply(Builder $builder, Model $model)
{
    $input = $this->getAuthValues(get_class($model));

    if (count($input) < 1) {
        throw new \Exception('No rights for you');
    }

    $jsonQuery = new JsonQuery($builder, $input); <-- class responsible for assembling the queries based on the input
    $jsonQuery->search();
}

但这当然也不例外。在这种情况下,我希望对空数组进行 returned。

我可以使用某种方法优雅地退出作用域并返回空结果,而无需随后实际执行查询吗?

由于作用域通常是链接的(流畅地调用),并且作用域不直接负责执行查询,我认为您不能“优雅地退出”,因为下一次调用仍会期待 Builder 要处理的对象。

一个可能的解决方案(不简单)是创建一个扩展 Builder class 的 class,并覆盖负责实际从中获取结果的所有方法D B。我不确定您需要重写的所有方法才能在所有情况下正常工作。您可能还想处理 AbortedBuilder 中的一些插入和更新情况。

class AbortedBuilder extends Builder
{
    ...

    /**
     * Run the query as a "select" statement against the connection.
     *
     * @return array
     */
    protected function runSelect()
    {
        return [];
    }
    
    ...

    /**
     * Run a pagination count query.
     *
     * @param  array  $columns
     * @return array
     */
    protected function runPaginationCountQuery($columns = ['*'])
    {
        return [];        
    }

    ...

    /**
     * Insert a new record and get the value of the primary key.
     *
     * @param  array  $values
     * @param  string|null  $sequence
     * @return int
     */
    public function insertGetId(array $values, $sequence = null)
    {
        throw new \Exception('You are trying to insert using an aborted query!');
    }

    ...
}

那么在你的范围内你可以做:

public function apply(Builder $builder, Model $model)
{
    $input = $this->getAuthValues(get_class($model));

    if (count($input) < 1) {
        $builder = new AbortedBuilder();
    } else {
        $jsonQuery = new JsonQuery($builder, $input);
        $jsonQuery->search();
}

我找到了一个解决方案来进行一个不可能的查询,该查询会 return 0 个结果。

public function apply(Builder $builder, Model $model)
{
    $input = $this->getAuthValues(get_class($model));

    if (count($input) < 1) {
        $builder->whereRaw('1 = 0');
        return;
    }

    $jsonQuery = new JsonQuery($builder, $input);
    $jsonQuery->search();
}