Laravel查询构建器查询指定日期可用车辆的问题求助
解决Laravel中查询指定日期区间可用车辆的问题
你的原查询逻辑存在两个核心问题:一是直接从bookings表取数据,但我们需要的是cars表的车辆信息;二是日期冲突的判断逻辑不正确,没覆盖到所有区间重叠的情况。
正确的思路
我们需要找出所有车辆中,不存在任何在$from到$till区间内且状态为booked的预订记录的车辆。判断两个日期区间是否重叠的充要条件是:
已预订记录的结束日期 >= 搜索起始日期 并且 已预订记录的起始日期 <= 搜索结束日期
基于这个逻辑,我们可以用两种方式实现:
方式一:使用查询构建器的whereNotExists子查询
这种方式适合没有定义Eloquent模型的场景:
$availableCars = DB::table('cars') ->whereNotExists(function ($query) use ($from, $till) { $query->select(DB::raw(1)) ->from('bookings') // 关联车辆表和预订表 ->whereColumn('bookings.car_id', 'cars.id') // 只考虑已确认的预订 ->where('bookings.status', '=', 'booked') // 判断日期区间是否重叠 ->where('bookings.till', '>=', $from) ->where('bookings.from', '<=', $till); }) ->get();
方式二:使用Eloquent模型的whereDoesntHave(推荐)
如果你已经定义了Car和Booking模型,并且设置了关联关系,这种方式更简洁:
首先确保Car模型中定义了与Booking的关联:
// app/Models/Car.php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Car extends Model { public function bookings() { return $this->hasMany(Booking::class); } }
然后执行查询:
use App\Models\Car; $availableCars = Car::whereDoesntHave('bookings', function ($query) use ($from, $till) { $query->where('status', 'booked') ->where('till', '>=', $from) ->where('from', '<=', $till); })->get();
为什么原查询会出错?
原查询直接从bookings表筛选from在搜索区间且status != 'booked'的记录,这完全偏离了需求:
- 我们需要的是车辆,不是预订记录;
- 即使某辆车有一条非
booked的预订记录,只要它还有其他在搜索区间内的booked记录,就应该被排除; - 原查询没有覆盖所有区间重叠的情况,比如当搜索区间完全包含已预订区间时,就会漏判冲突。
内容的提问来源于stack exchange,提问作者samuel komera
相关产品推荐
相关产品推荐

