php - 带有“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
?
解决方案
解决方案是为所有原始查询添加括号。
✅✅ 你可以看到我认为最成功的@Styx 解决方案
我也会留下我的答案,它直接作用于内部
global scope
,并且我认为能够看到一个\Illuminate\Database\Eloquent\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); } }
将此代码添加到您的
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()
调用都将自动在查询周围加上括号。
推荐阅读
- java - Selenium WebDriver 如何获取 WebElement 的按钮
- python - Python:如何在地图上绘制飞行轨迹/例程
- c# - 切换到 .net core 3 端点路由后,身份 UI 不再有效
- spring-mvc - 在 th:replace 中使用变量不会呈现模板
- excel - 如何从 Delphi 加速 Excel 格式化?
- java - 如何使用我的 java 应用程序控制 nginx 反向代理?
- algorithm - 将 n 个对象分成 k 个组的方法有多少种,使得没有一个组的对象比以前形成的组少?
- javascript - 删除firebase上的节点时出现问题
- aspose - 打开未使用密码加密的文档
- javascript - 我怎样才能打破表格的段落属性