为了账号安全,请及时绑定邮箱和手机立即绑定

优雅地退出 Laravel 作用域

优雅地退出 Laravel 作用域

PHP
繁星点点滴滴 2023-08-19 09:47:18
我有一个范围,它根据用户角色以限制方式起作用,您可以将一组规则转发到限制数据库最终输出的范围。一个非常简化的角色限制示例:{    "first_name": "=foo%"}只会返回first_name以 开头的记录foo%,这实际上意味着我已禁止具有该角色的用户查看任何不以 开头的记录foo%。这种方法的问题在于,如果某人没有施加任何限制,他就会看到一切。我知道这是一个有效的假设,但如果没有施加限制,我想禁止一切,这样如果创建了新角色,它就没有任何权利。目前我正在针对这种情况抛出异常: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();}但这当然也不例外。在这种情况下我希望返回空数组。我可以使用某种方法来优雅地退出范围并返回空结果,而无需在之后实际执行查询吗?
查看完整描述

2 回答

?
Cats萌萌

TA贡献1805条经验 获得超9个赞

我找到了一个解决方案来进行不可能的查询,该查询将返回 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();

}


查看完整回答
反对 回复 2023-08-19
?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

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


一种可能的解决方案(并不简单)是创建一个扩展该类的类Builder,并重写负责实际从数据库获取结果的所有方法。我不确定您需要重写的所有方法才能在所有情况下都没有错误地工作。您可能还想处理其中的一些插入和更新情况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();

}


查看完整回答
反对 回复 2023-08-19
  • 2 回答
  • 0 关注
  • 113 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信