You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:39:50