首页 > 解决方案 > 带有“OR”运算符的雄辩的“查询生成器”中和了我的全局范围 - Laravel

问题描述

⛳ 我需要什么:

我正在开发一个应用程序,Laravel 5.4我想要一个global scope允许我根据创建它们的用户过滤应用程序的不同元素的应用程序。


我的全球范围:

我有一个BaseEloquentModel.php扩展的类,Eloquent我的所有模型都从这个类扩展。我有一个global scope如下:

protected static function boot()
{
    parent::boot();
    static::addGlobalScope('', function(\Illuminate\Database\Eloquent\Builder $builder) use($userId) {
        /**
        * I get the name of the table with <code>(with(new static))->getTable()</code> 
        * and then filter the query for the <b>user_id</b> field
        */
        $builder->where(
            (with(new static))->getTable() . '.user_id', 
            '=',
            $userId
        );
    });
}

⛔ 问题

当我使用or运算符进行这样的查询时,全局范围为“中和”:

$qBuilderCars = Car::whereRaw("name like ? or id = ?", [
    '%' . $searchCriteria. '%',
    $searchCriteria
]);

如果我调用该toSql()方法, $qBuilderCars我会看到它“正确”地AND运算符添加到查询的末尾。

select * from `cars` where name like ? or id = ? and user_id = ?

也许你已经注意到我的问题了......如果元素的构建器在这种情况下cars使用了OR运算符,那么全局范围将无济于事,因为 . 之间没有括号where name like ? or id = ?。因此,生成的查询将类似于以下内容:

select * from `cars` where name like ? (or id = ? and user_id = ?)

因此,此查询将返回名称匹配或 ID 为已接收并由用户创建的所有汽车...

当我需要的是:

select * from `cars` where (name like ? or id = ?) and user_id = ?

我的尝试

我试图改变 myglobal scope以尝试使AND我在查询中添加的运算符最严格,但没有任何成功。

我不能手动为所有应用程序的查询添加括号,所以......有没有办法将全局括号从全局范围添加到builder


解决方案

解决方案是为所有原始查询添加括号。

标签: phplaraveleloquentscope

解决方案


好吧,您添加括号的解决方案似乎是最好的解决方法,但我有一个建议,如何做到这一点稍微好一点。

  1. 创建新类QueryBuilder。例如,在\App\Models\命名空间(app/Models/文件夹)中:

    namespace App\Models;
    
    use Illuminate\Database\Query\Builder as EloquentQueryBuilder;
    
    class QueryBuilder extends EloquentQueryBuilder {
    
      public function whereRaw($sql, $bindings = [], $boolean = 'and')
      {
        return parent::whereRaw('('.$sql.')', $bindings, $boolean);
      }
    
    }
    
  2. 将此代码添加到您的BaseEloquentModel课程中:

    use Illuminate\Database\Eloquent\Model;
    use App\Models\QueryBuilder; // <-- addition
    
    class BaseEloquentModel extends Model {
      // ...
      protected function newBaseQueryBuilder()
      {
        $connection = $this->getConnection();
    
        return new QueryBuilder(
            $connection,
            $connection->getQueryGrammar(),
            $connection->getPostProcessor()
        );
      }
      // ...
    }
    

现在,所有whereRaw()调用都将自动在查询周​​围加上括号。


推荐阅读