我目前只能使用一个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|
查询仍然返回两个日期,即使其中之一为假。我认为该查询会查找数据库中的所有记录,并且仍然返回给定的用户,因为其中一个日期是正确的。我的问题是,是否可以仅将数据库中的最新行作为目标。否则这不能用雄辩的方式完成。任何帮助表示赞赏。
编辑:
正如@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
的努力,我设法获得了预期的结果。我只是更改条件以监视未在给定日期创建账单的客户。查询范围:
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();
});
答案 0 :(得分:1)
您正在寻找的是像这样的关系查询范围
$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"
}
]
}
]
希望这会有所帮助
答案 1 :(得分:0)
您可以使用Eloquent whereDate()。
->whereDate('created_at', '<', Carbon::parse($activeSchoolYear->start));