Laravel过滤器嵌套关系

时间:2020-08-02 11:26:54

标签: php laravel eloquent eloquent-relationship

因此,我有三种模式:志愿者,任务和支付。志愿者可以有很多(有很多关系)任务,而一个任务可以有很多(另一个有很多关系)支付。

class Volunteer

public function tasks()
{
    return $this->hasMany(Task::class);
}

class Task

  public function volunteer()
{
    return $this->belongsTo(Volunteer::class);
}

 public function payments()
{
    return $this->hasMany(Payment::class);
}

class Payment 

public function task() {
    return $this->belongsTo(Task::class);
}

现在,我想查询所有未付费/部分付费任务的志愿者。因此,基本上,我想过滤一个志愿者的任务,其中每个任务的金额应等于与该特定任务相关的所有付款的总和。

我尝试使用whereHas和with,但似乎无法正确过滤任务。

我已经设法通过连接来做到这一点,但我想知道是否可以使用whereHas或with。下面是代码:

Volunteer::select('volunteers.id', 'volunteers.name', 'tasks.amount', DB::raw('SUM(payments.amount) as amount_paid'))
        ->join('tasks', 'tasks.volunteer_id', '=', 'volunteers.id')
        ->leftJoin('payments', 'payments.task_id', '=', 'tasks.id')
        ->groupBy('volunteers.id', 'volunteers.name', 'tasks.amount')
        ->havingRaw('amount_paid >= tasks.amount')
        ->get();

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

我想提出其他建议,那就是在tasks表中添加一列,以指示在您的tasks迁移过程中任务是[已付款,未付款还是部分付款]

$table->unsignedTinyInteger('paid_status')->default(0); // 0 -> unpaid, 1 -> partially paid, 2 -> paid

然后,每当志愿者付款时,您都会进行一次简单的检查来更新tasks.paid_status,例如检查总计paid_amount和任务amount

然后在hasManyThrough模型中使用Laravel Volunteer

public function payments()
{
   return $this->hasManyThrough(
       'App\Payment',
       'App\Task'
  );
}

现在要获取您的数据

// unpaid tasks
Volunteer::query()->first()->payments()->where('tasks.paid_status', '0')->get();
// partially paid tasks
Volunteer::query()->first()->payments()->where('tasks.paid_status', '1')->get();
// paid tasks
Volunteer::query()->first()->payments()->where('tasks.paid_status', '2')->get();

您可以阅读有关HasManyThrough Here

的更多信息

答案 1 :(得分:0)

您也可以使用雄辩的力量来处理此问题。使用local scope方法扩展任务模型

class Task extends Model
{
    public function volunteer()
    {
        return $this->belongsTo(Volunteer::class);
    }

    public function payments()
    {
        return $this->hasMany(Payment::class);
    }

    public function scopeIncompletePayments($query)
    {
        return $query->select('tasks.*')->leftJoin('payments', 'tasks.id', '=', 'payments.task_id')
            ->having('tasks.amount', '>', DB::raw('SUM(payments.amount)'))
            ->groupBy('tasks.id')
            ->with(['volunteer', 'payments']);
    }
}

其中,您可以运行以下代码来获取相关付款总额小于任务金额的任务。随着付款和志愿者的热切

Task::incompletePayments()->get()