【问题标题】:Laravel Eloquent get where doesnt have, search where has when not nullLaravel Eloquent 获取 where 没有,搜索 wherehas 时不为空
【发布时间】:2018-08-30 11:13:08
【问题描述】:

这个问题真的很难说,所以我为标题道歉!

假设我有一个Rooms 模型和一个Bookings 模型,1 个房间可以有多个预订。

我正在构建一个带有过滤器的表,如果有预订,我需要能够对预订关系运行过滤器,否则无论如何都要抓取记录。

假设我的房间有这样的预订关系

public function latestBooking(){
    return $this->hasOne('App\Models\Bookings', 'room_id', 'id')
    ->orderBy('expiry_date', 'DESC')->limit(1);
}

上述关系为我提供了最新的预订。

我正在像这样运行一个“空置”过滤器

if ($request->has('filters.vacant_from')) {
    $rooms = $rooms->whereHas('latestBooking', function ($query) use ($request) {
        $query->where('expiry_date', '<', Carbon::createFromFormat('d/m/Y',$request->input('filters.vacant_from'))->format('Y-m-d'));
    });
}

问题在于,这只会获取已预订且在指定日期之后可用的房间。我需要它能够搜索所有房间,如果它确实有预订,请检查到期日期是否在指定日期之后,如果它没有最新预订,则将其作为空房间获取。

基本上我将如何构建我的过滤器函数,使其像这样运行

搜索所有房间,如果有最新预订,请检查其到期日期是否在指定日期之后,只有在其真实/空置时才抓取它,如果它没有最新预订,则无论如何都要抓取它它是空的

【问题讨论】:

    标签: php laravel laravel-5 eloquent


    【解决方案1】:

    我有一个关于您的latestBookingRelationship 的建议。您应该创建另一个关系并向其添加greater than today 条件,并可能将其命名为activeLatestBooking。

    然后,您的最新预订应包括所有预订房间,无论其预订是否有效。

    public function activeLatestBooking(){
            return $this->hasOne('App\Models\Bookings', 'room_id', 'id')
            ->where('expiry_date', '>', date('d/m/Y', strtotime('today')))->orderBy('expiry_date', 'DESC')->limit(1);
        }
    
    public function latestBooking(){
        return $this->hasOne('App\Models\Bookings', 'room_id', 'id')
        ->orderBy('expiry_date', 'DESC')->limit(1);
    }
    

    那么,回答你的问题:

    if ($request->has('filters.vacant_from')) {
            $rooms = $rooms->whereHas('latestBooking', function ($query) use ($request) {
                $query->where('expiry_date', '<', Carbon::createFromFormat('d/m/Y',$request->input('filters.vacant_from'))->format('Y-m-d'));
            })->orWhereDoesntHave('latestBooking');
        }
    

    过滤查询的作用是:它获取expiry_date 小于vacant_from 日期的所有最新预订...而orWhereDoesntHave 获取所有从未被预订的房间。

    【讨论】:

    • 添加'orWhereDoesntHave',我认为是实现我的目标的最干净的方法。谢谢!
    【解决方案2】:

    预订关系应该是这样的,

    public function latestBooking(){
        return $this->hasMany('App\Models\Bookings')->orderBy('expiry_date', 'DESC');
    }
    

    因为这是一对多的关系。 laravel relationship

    你可以这样写你的过滤器,

      if ($request->has('filters.vacant_from')) {
            $rooms = $rooms->whereHas('latestBooking', function ($query) use ($request) {
                $query->whereDate('expiry_date', '<', Carbon::createFromFormat('d/m/Y',$request->input('filters.vacant_from'))->format('Y-m-d'));
            });
        }
    

    你可以使用 whereDate 在 laravel 中运行日期查询。希望这会有所帮助

    【讨论】:

      【解决方案3】:

      假设您在 Rooms 和 Bookings 名称为 bookings 的模型之间有 hasMany 关系

      $rooms = Rooms::whereHas('bookings', function ($query) use ($request) {
                  $query->whereDate('expiry_date', '<', Carbon::createFromFormat('d/m/Y',$request->input('filters.vacant_from'))->format('Y-m-d'));
              })->orWhereDoesntHave('bookings')->get();
      

      【讨论】:

      • 但这不是只返回没有预订的行吗?
      • 但这只是搜索没有最新预订的行?我需要它是“如果它有预订,搜索,如果它没有预订,也抓住它”
      • 它将搜索没有预订或有预订但过期日期早于搜索日期。无需查看最新预订。只是为了检查房间是否被预订然后它的过期日期是否在搜索日期之前然后返回
      猜你喜欢
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      • 1970-01-01
      • 2021-08-23
      • 1970-01-01
      • 2019-12-28
      • 2017-06-09
      相关资源
      最近更新 更多