php - Laravel 雄辩查询的高级 where
问题描述
我目前被困在一个where
Laravel 查询上。问题是,我想根据给定表中的最新记录过滤一些数据。目前,我的查询如下所示:
$clients = $clients->whereDoesntHave('bill')->orWhereHas('bill', function ($query) use ($activeSchoolYear){
$query
->where('created_at', '<', Carbon::parse($activeSchoolYear->start));
})
$activeSchoolYear->start
今天的日期在哪里。
如果我的账单表中有多条记录,就会出现问题。例如,如果我有两条不同日期的记录:
ID | Name | created_at |
1 | test | 2019-09-09 15:31:25|
2 | test2 | 2018-09-10 16:42:44|
查询仍然返回两个日期,即使其中一个为假。我认为该查询会查找数据库中的所有记录,并且仍然返回给定的用户,因为其中一个日期是正确的。我的问题是,是否可以仅针对数据库中的最新行。或者这不能使用 eloquent 来完成。任何帮助表示赞赏。
编辑:
正如@Caddy 建议的那样,我使用了查询范围,但我对其进行了一些修改:
public function scopeNoActiveBill($query){
return $query
->groupBy('created_at')->take(1)
->where('created_at', '<=', Carbon::create(2019, 9, 1));
}
我试图只从账单表中取出最后一行。然后,在控制器内部,这是我的查询:
$clients = $clients->whereDoesntHave('bill')
->orWhereHas('bill', function ($query) use ($activeSchoolYear){
$query->noActiveBill();
})
->whereHas('contracts', function ($query) use ($request) {
$query
->where('contract_type', '<', 2)
->where('signed', 1)
->where('school_year_id', $request['school_year']);
});
所以,我希望两个客户都没有任何账单,或者客户的账单符合给定标准。如果客户只有一张账单,则查询可以正常工作,但问题是当客户有多张账单时。如果这些账单中的任何一个符合给定范围,它就会返回该账单。我只想检查最新的记录,如果该记录符合范围标准,则返回账单。
编辑2:
感谢@Caddy DZ
's asnwer,我设法得到了想要的结果。我只是更改了条件以监视在给定日期之前没有创建账单的客户。查询范围:
public function scopeNoActiveBill($query){
return $query->where('created_at', '>=', Carbon::create(2019, 9, 1));
}
控制器:
$clients = $clients->whereDoesntHave('bill')
->orWhereDoesntHave('bill', function ($query) use ($activeSchoolYear){
$query->noActiveBill();
});
解决方案
您正在寻找的是这样的关系查询范围
$clients = App\Client::with(['bills' => function ($query) {
$query->today();
}])->get();
像这样为您的模型添加today()
范围Bill
Bill.php
public function scopeToday($query)
{
// Change today by $activeSchoolYear if necessary
return $query->whereDate('created_at', '<', today());
}
假设hasMany
关系在Client
public function bills()
{
return $this->hasMany(Bill::class);
}
像这样播种的数据
DatabaseSeeder.php
// Will be returned because whereDoesntHave('bills')
$clientWithoutBills = Client::create([]);
$client = Client::create([]);
$client->bills()->createMany([
[
'name' => 'test',
'created_at' => Carbon\Carbon::yesterday()
],
[
// Will not be returned because created today (not < today)
'name' => 'test1'
],
[
// Will not be returned because created tomorrow
'name' => 'test2',
'created_at' => Carbon\Carbon::tomorrow()
]
]);
Results
[
{
"id": 1,
"created_at": "2019-09-09 16:20:24",
"updated_at": "2019-09-09 16:20:24",
"bills": []
},
{
"id": 2,
"created_at": "2019-09-09 16:20:24",
"updated_at": "2019-09-09 16:20:24",
"bills": [
{
"id": 1,
"name": "test",
"client_id": 2,
"created_at": "2019-09-08 00:00:00",
"updated_at": "2019-09-09 16:20:24"
}
]
}
]
希望这可以帮助
推荐阅读
- java - 如何在 Hibernate Envers withModifiedFlag = true 中更改列的列表字符串
- ms-access - VBA循环通过价格范围
- keras - 模型对于相同的输入有不同的输出
- java - Java 应用程序变慢并且需要更多时间来更新 UI
- reactjs - 向组件返回添加循环
- angularjs - 是否可以使用 ng-class 将值插入到类名中?
- php - 无法在 Composer 中删除未使用的包
- swift - 在 Swift 4 中将图像上传到 Firebase 存储
- php - codeigniter 3.x 中的 MongoDB\Driver\Exception\InvalidArgumentException
- json - 将网页/JSON 中的单个值导入 Google 电子表格