tom*_*rod 8 php scope laravel eloquent
我正在开发一个应用程序,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
);
});
}
Run Code Online (Sandbox Code Playgroud)
当我有这样的查询,使用or运算符时,全局作用域被“中和”:
$qBuilderCars = Car::whereRaw("name like ? or id = ?", [
'%' . $searchCriteria. '%',
$searchCriteria
]);
Run Code Online (Sandbox Code Playgroud)
如果在toSql()上调用该方法 $qBuilderCars,则会看到它“正确”地将AND运算符添加到查询的末尾。
select * from `cars` where name like ? or id = ? and user_id = ?
Run Code Online (Sandbox Code Playgroud)
也许您已经注意到了我的问题...在这种情况下cars,如果元素的生成器使用了OR运算符,则全局作用域将无济于事,因为之间没有括号where name like ? or id = ?。因此,产生的查询将类似于以下内容:
select * from `cars` where name like ? (or id = ? and user_id = ?)
Run Code Online (Sandbox Code Playgroud)
因此,此查询将返回所有名称匹配或ID为已接收并由用户创建的汽车。
当我需要的是:
select * from `cars` where (name like ? or id = ?) and user_id = ?
Run Code Online (Sandbox Code Playgroud)
我试图改变我的方法global scope,试图使AND我在查询中添加最严格的运算符,但没有成功。
我无法将括号手动添加到所有应用程序的查询中,所以...有没有办法将全局范围内的全局括号添加到builder?
解决方案是在所有原始查询中添加括号。
好吧,看来您添加括号的解决方案是最好的解决方法,但我有一个建议,如何做稍微更好的方法。
创建新类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);
}
}
Run Code Online (Sandbox Code Playgroud)将此代码添加到您的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()
);
}
// ...
}
Run Code Online (Sandbox Code Playgroud)现在,所有whereRaw()调用都会自动在查询周围添加括号。