【问题标题】:Laravel queries: Get all vehicles without bookings in specific date rangeLaravel 查询:获取特定日期范围内没有预订的所有车辆
【发布时间】:2020-05-25 15:05:42
【问题描述】:

这些是我的 vehiclebooking 模型:

class Booking extends Model
{
    ....
    public function vehicle(){
        return $this->belongsTo('App\Models\Vehicle', 'vehicle_id');
    }
    ....
}

class Vehicle extends Model
{
    ....
    public function bookings(){
        return $this->hasMany('App\Models\Booking', 'vehicle_id');
    }
    ....
}

在我的控制器中,我想获取在给定日期没有预订的所有车辆,所以这是我迄今为止尝试过的:

public function availabillity(Request $request){

        $bookings = Booking::query();
        $vehicles = Vehicle::query();

        $selectedStart = Carbon::createFromFormat('d/m/Y H:i',  $request['start']); 
        $selectedEnd =  Carbon::createFromFormat('d/m/Y H:i',  $request['end']);
        //$availableVehicles = [];

        $availableVehicles = $vehicles->select('vehicles.id')->leftjoin('bookings', function ($join) use ($selectedStart, $selectedEnd){
            $join->on('vehicles.id', '=', 'bookings.vehicle_id')
                ->where([
                        ['bookings.start', '<',$selectedStart], //selected start is between booking dates
                        ['bookings.end', '>', $selectedStart]
                    ])->orWhere([
                        ['bookings.start', '<',$selectedEnd],   //selected end is between boking dates
                        ['bookings.end', '>', $selectedEnd]
                    ])->orWhere([
                        ['bookings.start', '>',$selectedStart],  //booking dates are between selected start and selected end
                        ['bookings.end', '<', $selectedEnd]
                    ]);
            })->distinct('vehicles.id')->get();


       $res = [];
       $res['vehicles'] = $availableVehicles;
       $res['selected_start'] = $selectedStart ;
       $res['selected_end'] = $selectedEnd;

       return response($res);


    }

但它不起作用。即使我通过以下方式预订,我仍然可以获得所有车辆:

start: 2020-02-05 11:40:00
end:   2020-02-10 12:40:00

我的要求是日期:

start: 2020-02-05 12:01:00
end:   2020-02-12 12:00:00

如何修改查询以获得可用车辆?有没有比复杂查询更有效的方法?也许通过改变我的模型?

编辑

这些是我的桌子:

预订:

+----+---------------------+---------------------+------------+
| id | start               | end                 | vehicle_id |
+----+---------------------+---------------------+------------+
| 29 | 2020-02-05 11:40:00 | 2020-02-10 12:40:00 | 38         |
+----+---------------------+---------------------+------------+

车辆

+----+
| id |
+----+
| 37 |
+----+
| 38 |
+----+
| 39 |
+----+
| 40 |
+----+

所以根据我希望得到的输入日期:

37,39,40

相反,我得到所有车辆 ID

【问题讨论】:

  • 如果是我,我会从sql开始。
  • @Strawberry 有什么建议吗?
  • @Strawberry 我添加了表格和预期结果...
  • 好。需要注意的是,该解决方案包含的代码比绝对必要的要多。一般来说,事件A和B重叠id事件B在事件A结束之前开始,在事件A开始之后结束。

标签: php mysql laravel join eloquent


【解决方案1】:

我认为这里的问题是您使用的是orWhere,它将返回满足其中一个条件的每一行,而这恰好是所有条件。

orWhere 更改为where,它将使用“and”而不是“or”,它应该可以工作。

【讨论】:

  • 但我使用的是左连接。所以我想要所有不满足任何条件的行。这就是我使用 OR 的原因。我尝试使用where,但仍然得到相同的结果。
  • 那么你应该使用相反的条件,即改变每个 > 为
  • 但我猜它不会是左连接
【解决方案2】:
public function availabillity(Request $request){

    $selectedStart = Carbon::createFromFormat('d/m/Y H:i',  $request['start']); 
    $selectedEnd =  Carbon::createFromFormat('d/m/Y H:i',  $request['end']);
    //$availableVehicles = [];

    $availableVehicles = $vehicles->whereDoesntHave('bookings', function($query) use ($selectedStart, $selectedEnd) {
        $query->where([
                    ['bookings.start', '<',$selectedEnd], 
                    ['bookings.end', '>', $selectedStart]
                ]);
    })->get();


   $res = [];
   $res['vehicles'] = $availableVehicles;
   $res['selected_start'] = $selectedStart ;
   $res['selected_end'] = $selectedEnd;

   return response($res);


}

【讨论】:

  • ErrorException: 类 Closure 的对象无法转换为文件中的字符串
  • [ ] 添加到doesntHave(['bookings' =&gt; function])
  • 我更改了 whereDoesntHave 并且没有收到任何错误。但我仍然得到所有的汽车
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多