简体   繁体   English

Laravel 过滤器嵌套关系

[英]Laravel filter nested relationship

So I have three models: Volunteer, Task and Payment.所以我有三种模式:志愿者、任务和付款。 A Volunteer can have many (has many relationship) tasks and a task can have many (another has many relationship) payments.一个志愿者可以有很多(有很多关系)任务,一个任务可以有很多(另一个有很多关系)付款。

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);
}

Now I want to query all volunteers with unpaid/ partially paid tasks.现在我想查询所有有无偿/部分有偿任务的志愿者。 So, basically I want to filter a volunteer's tasks where each task's amount should equal the sum of all payments linked to that particular task.所以,基本上我想过滤志愿者的任务,其中每个任务的金额应该等于与该特定任务相关的所有付款的总和。

I tried using whereHas and with but I don't seem to be able to filter the tasks properly.我尝试使用 whereHas 和 with 但我似乎无法正确过滤任务。

I've managed to do it with joins but was wondering if it's possible to with whereHas or with.我已经设法通过加入来做到这一点,但想知道是否可以使用 whereHas 或 with。 Below is the code:下面是代码:

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

Any help would be appreciated!任何帮助,将不胜感激!

I would like to suggest something else which is adding a column in tasks table that indicates if the task is [paid, unpaid or partially paid] in your tasks migration like so我想提出其他建议,即在tasks表中添加一列,指示任务在您的tasks迁移中是否为[付费、未付费或部分付费],如下所示

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

then each time the volunteer makes a payments you will do a simple check to update tasks.paid_status something like checking the total paid_amount and task amount然后每次志愿者付款时,您都会做一个简单的检查来更新tasks.paid_status就像检查总paid_amount和任务amount

then using Laravel hasManyThrough in Volunteer model like so然后在Volunteer model 中使用 Laravel hasManyThrough像这样

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

now to get your data you will do so现在要获取您的数据,您将这样做

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

you can read more about HasManyThrough Here您可以在此处阅读有关 HasManyThrough 的更多信息

You can handle this using the eloquent powers as well.您也可以使用 eloquent 电源来处理此问题。 Extends the Task model with a local scope method使用本地 scope方法扩展任务 model

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']);
    }
}

Which allows you to run the following code to get the tasks where the sum of the related payments is less than the amount of the task.这允许您运行以下代码来获取相关付款总和小于任务金额的任务。 With the payments and Volunteer eagerly loaded随着付款和志愿者热切地加载

Task::incompletePayments()->get()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM