代码之家  ›  专栏  ›  技术社区  ›  ashanrupasinghe

Laravel-在没有检查其他人的情况下检查一段关系的最新记录

  •  0
  • ashanrupasinghe  · 技术社区  · 7 年前

    我有两个表有一对多的关系。

    (id)

    预订任务- (id, booking_id,user_id)

    预订模式:

     public function tasks() {
        return $this->hasMany('App\BookingTask');    
      }
    

    预订任务模型

    public function booking() {
        return $this->belongsTo('App\Booking');
    } 
    

    我要订一张,

    前任:

    enter image description here

    我想检查预订任务的用户id=2的最后一条记录是否作为预订获取。 在这个例子中,上一个预订任务的用户id=5。所以它不会作为预订得到。

    我的代码是:

    $bookings=Booking::whereHas('tasks',function($q){
                $q->where('user_id',2);//this will check whether any of record has user_id =2
    })->get();
    

    我也用了这个:

    $bookings=Booking::whereHas('tasks',function($q){
                    $q->latest()->where('user_id',2)->limit(1);//this will check whether any of record has user_id =2 and return latest one.
        })->get();
    

    4 回复  |  直到 7 年前
        1
  •  12
  •   Jonas Staudenmeir    7 年前

    这需要更复杂的查询:

    $bookings = Booking::select('bookings.*')
        ->join('booking_tasks', 'bookings.id', 'booking_tasks.booking_id')
        ->where('booking_tasks.user_id', 2)
        ->where('booking_tasks.id', function($query) {
            $query->select('id')
                ->from('booking_tasks')
                ->whereColumn('booking_id', 'bookings.id')
                ->latest()
                ->limit(1);
        })->get();
    
        2
  •  2
  •   Simon    7 年前

    我发现Jonas的答案是有效的,但是因为它是一个带有连接的查询,所以它导致了从模型中加载关系的问题。所以我用这个方法 whereHas

    第一步是向查询中添加宏 Builder AppServiceProvider .

    use Illuminate\Database\Query\Builder;
    
    Builder::macro('whereLatestRelation', function ($table, $parentRelatedColumn) 
    {
        return $this->where($table . '.id', function ($sub) use ($table, $parentRelatedColumn) {
            $sub->select('id')
                ->from($table . ' AS other')
                ->whereColumn('other.' . $parentRelatedColumn, $table . '.' . $parentRelatedColumn)
                ->latest()
                ->take(1);
        });
    });
    

    这基本上使Jonas答案的子查询部分更通用,允许您指定联接表和它们联接的列。它假定另一列是“id”列,因此可以进一步改进。要使用它,您可以执行以下操作:

    $userId = 2;
    Booking::whereHas('tasks', function ($tasks) use ($userId) {
        $tasks->where('user_id', $userId)
            ->whereLatestRelation((new Task)->getTable(), 'booking_id');
    });
    

        3
  •  0
  •   John Halsey    7 年前

    这个

    没什么意义,但我 认为 您想要退出的是所有用户\u id==2的预订,其中至少有1个任务和 每次预订的最新任务是什么?所以也许这会奏效?

    Booking::where('user_id', 2)->with('tasks', function($query){
        $query->orderBy('created_at', 'DESC')->take(1);
    })->has('tasks')->get();
    
        4
  •  -1
  •   Sergey Poprovka    7 年前