Laravel过滤嵌套关系
Laravel filter nested 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();
如有任何帮助,我们将不胜感激!
我想提出一些其他建议,即在 tasks
table 中添加一列,指示您的 tasks
迁移中的任务是 [付费、未付费或部分付费]像这样
$table->unsignedTinyInteger('paid_status')->default(0); // 0 -> unpaid, 1 -> partially paid, 2 -> paid
然后每次志愿者付款时,您都会做一个简单的检查来更新 tasks.paid_status
,比如检查总数 paid_amount
和任务 amount
然后在 Volunteer
模型中使用 Laravel hasManyThrough
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
你也可以使用 eloquent 的能力来处理这个问题。使用 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()
所以我有三个模型:志愿者、任务和付款。一个志愿者可以有很多(有很多关系)任务,一个任务可以有很多(另一个有很多关系)付款。
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();
如有任何帮助,我们将不胜感激!
我想提出一些其他建议,即在 tasks
table 中添加一列,指示您的 tasks
迁移中的任务是 [付费、未付费或部分付费]像这样
$table->unsignedTinyInteger('paid_status')->default(0); // 0 -> unpaid, 1 -> partially paid, 2 -> paid
然后每次志愿者付款时,您都会做一个简单的检查来更新 tasks.paid_status
,比如检查总数 paid_amount
和任务 amount
然后在 Volunteer
模型中使用 Laravel hasManyThrough
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
你也可以使用 eloquent 的能力来处理这个问题。使用 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()