Laravel-在不检查他人的情况下检查关系的最新记录的地方

时间:2018-11-02 08:30:48

标签: php sql-server laravel-5 eloquent

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

预订-(id)

booking_tasks-(id, booking_id,user_id)

一个预订有很多任务 一个任务有一个预订

预订模式:

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

BookingTask模型

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

我想获取预订清单, user_id = 2,表示最近的预订任务。我不想检查其他旧的Booking_tasks。

例如:

enter image description here

我想检查booking_task的user_id = 2的最后一条记录是否可以作为预订。 在示例中,最后一个booking_task的user_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();

我该如何解决这个问题,我也必须使用Laravel Eloquent。

4 个答案:

答案 0 :(得分:4)

这需要更复杂的查询:

$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();

答案 1 :(得分:0)

您是否尝试过-> first()与相反的orderBy()组合?

类似于$ q-> where('user_id','=','2')-> orderBy('id','DESC')-> first();

答案 2 :(得分:0)

  

我想获取预订清单,其中user_id = 2代表最新的booking_task。我不想检查其他旧的Booking_tasks。

没有太多意义,但是我想想的是,出去所有带有user_id == 2的预订,其中至少有1个任务且每次预订仅最新任务?所以也许这行得通?

Booking::where('user_id', 2)->with('tasks', function($query){
    $query->orderBy('created_at', 'DESC')->take(1);
})->has('tasks')->get();

答案 3 :(得分:0)

我发现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');
});

与接受的答案逻辑相同,但重用起来更容易。但是,它会慢一些,但是值得重复使用。