如何编写查询筛选未在指定日期区间被租用的汽车模型?
解决未在指定日期区间被租用的汽车查询问题
原代码的问题分析
- 逻辑方向错误:
whereHas是筛选存在符合条件订单的汽车,但我们需要的是没有任何与目标日期区间冲突的订单的汽车,逻辑完全相反。 - 日期重叠判断错误:判断订单与目标区间无重叠的正确逻辑应该是「订单结束日期早于目标区间开始,或者订单开始日期晚于目标区间结束」,原代码的
whereNotBetween组合会遗漏大量冲突场景(比如订单跨区间的情况)。 - 语法错误:
whereNotBetween的第二个参数应为数组格式([$fromDate, $toDate]),且原代码中变量引用($date, $data)明显是$fromDate, $toDate的笔误,同时括号匹配也存在问题。
正确查询方案
方案1:包含无任何订单的汽车(最常用场景)
如果要覆盖从未被租用的汽车,直接排除所有存在冲突订单的车辆即可:
$query->whereDoesntHave('orders', function ($query) use ($fromDate, $toDate) { // 判断订单与目标区间存在重叠的核心条件 $query->where('rental_start_date', '<=', $toDate) ->where('rental_end_date', '>=', $fromDate); });
方案2:仅筛选有订单但无冲突的汽车
如果只需要已经有租用记录,但所有订单都不与目标区间冲突的汽车,可结合whereHas和whereDoesntHave:
$query->whereHas('orders') ->whereDoesntHave('orders', function ($query) use ($fromDate, $toDate) { $query->where('rental_start_date', '<=', $toDate) ->where('rental_end_date', '>=', $fromDate); });
日期重叠判断逻辑说明
两个日期区间[A_start, A_end]和[B_start, B_end]存在重叠的判定条件是:A_start <= B_end AND A_end >= B_start
反过来,无重叠的条件就是:A_end < B_start OR A_start > B_end
我们通过排除存在重叠订单的汽车,就能精准得到目标日期区间内可租用的车辆列表。
内容的提问来源于stack exchange,提问作者AbdiMed
相关产品推荐
相关产品推荐

