【发布时间】:2016-07-29 16:55:27
【问题描述】:
这是我在这里的第一篇文章,所以请原谅任何错误:)
我目前正在从事库存管理应用程序(Laravel)的项目。我到了我所做的任何事情都不起作用的地步,所以现在我请求帮助。
我有一张产品表,其中一些与其他产品有关系。一切都发生在一张桌子上。如果产品有子级,则子级会覆盖父级。
然后,我对它们运行的所有查询都使用以下逻辑:
- 如果该项目没有任何子项,请使用它。
- 如果项目有子项,请使用最新的子项(最高 id)
现在我在模型文件中创建了关系:
public function childItems(){
return $this->hasMany('\App\OrderItem','parent_id');
}
public function parentItem(){
return $this->belongsTo('\App\OrderItem','parent_id');
}
public function latestChild(){
return $this->hasOne('\App\OrderItem','parent_id')->orderBy('id','desc')->limit(1);
}
latestChild() 关系的问题在于,当您运行此查询时:
\App\OrderItem::find(7)->latestChild()->get()
它工作正常并且只返回一个(最新的)(id 6)关系记录 - 为此我必须添加 orderBy 和限制到 hasOne()。
但是当我想在作用域中使用这种关系时,在 whereHas 方法中,它不能正常工作,因为它需要任何孩子而不是最新的。
public function scopeDue($query){
return $query->where(function($q){
$q->has('childItems','==',0)->has('parentItem','==',0)->whereDate('due_date','=', Carbon::today()->toDateString())->whereNull('return_date');
})->orWhere(function($q2){
$q2->has('childItems')->has('parentItem','==',0)->whereHas('childItems',function($q3) use($q2){
$q3->whereDate('due_date','=', Carbon::today()->toDateString())->whereNull('return_date');
});
})->with('latestChild');
}
但是,with() 在最后返回正确的记录。
我认为,它之所以如此有效,是因为我的关系 latestChild() 返回所有子项(尽管有 hasOne()),并且当我在 whereHas 中使用它时,它忽略了我应用的过滤功能。
我知道我的描述有点复杂,但为了更好地解释它,我将使用一个示例。在修补程序中执行以下操作
\App\OrderItem::due()->get();
应该只返回记录 id 2,因为数字 7 有孩子,当然 id 5 是到期的,但最新的孩子是 id 6,没有到期。
我希望我已经对它进行了足够的解释,以便让您帮助我,因为我已经为此发疯了。 如果您对如何通过更改现有的或更改其整体逻辑来实现我的需求有任何想法,请提供帮助!
谢谢, 达雷克
【问题讨论】:
-
您好!我遇到了同样的问题,无法通过 ONLY 最后一个相关的模型过滤模型...你能解决这个问题吗?谢谢。
-
@Zalo 有一种稍微不同的做法,就是在父模型上使用一个子选择列来选择最新的孩子的id,然后可以用来加入对应的孩子。我之前确实回答了一个非常相似的问题here。
标签: laravel eloquent relationship