使用Laravel Eloquents HasManyThrough通过多态关系与多个关系

时间:2015-04-23 13:11:56

标签: php laravel polymorphism laravel-5

我有一个相当简单的应用程序,用户可以报告其他用户的评论和食谱。我使用多态关系来存储报告。哪个工作正常;但是,我现在正在努力解决用户犯下的罪行。

获取用户报告不是问题,可以使用inline直接完成,但我非常希望获得其他人报告该用户的报告。我可以使用user->reports()关系或查询,但一次只能在一个模型上使用。

离。

hasManyThrough

或者

public function offenses() {
    return $this->hasManyThrough('Recipe', 'Reports');
}

问题是我的可报告对象不仅仅是食谱,它可能是注释,图像等。因此,不必使用多个函数,逻辑方法是以某种方式解析hasManyThrough各种参数之间的关系。

理论上看起来像这样:

->with('user.recipe.reports')

这有可能吗?有一些没有文档的语法?如果不是,有任何聪明的解决方法/黑客?

可能的解决方案?

可接受的解决方案是在我的报告表上添加另一列,只添加像这样的offender_id吗?

ID | User_id | Offender_id | Reportable_type | Reportable_id

这意味着我可以在我的用户模型上建立关系,通过该列连接攻击。但这会被视为多余吗?既然我已经通过可报告的模型犯罪了吗?

模型

多态模型

public function offenses() {
    return $this->hasManyThrough(['Recipe', 'RecipeComments'], 'Reports');
}

食谱模型

class Report extends Model {
    public function reportable() {
        return $this->morphTo();
    }

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

评论模型

class Recipe extends Model {
    public function user() {
        return $this->belongsTo('App\User');
    }

    public function reports() {
        return $this->morphMany('App\Report', 'reportable');
    }
}

1 个答案:

答案 0 :(得分:2)

使用您当前的模型,您可以通过以下代码接收用户的所有报告模型:

$recipeCommentReport = RecipeComment::whereHas('reports',function($q){
   return $q->where('user_id','=',Auth::user()->id) 
});

$recipeReport = Recipe::whereHas('reports',function($q){
   return $q->where('user_id','=',Auth::user()->id) 
});

//Get all reports into one
$reports = $recipeReport->merge([$recipeCommentReport]);

这充其量是混乱的,因为:

  1. 我们无法对结果进行排序,因为我们使用了两个单独的数据库查询。
  2. 如果您有其他具有报告关系的模型,请想象一下混乱。
  3. 最佳解决方案,正如您在上面已经想到的那样:

    offender_id表格中添加report列。

    它更干净,遵循DRY原则。

    典型案例场景

    获取用户的所有食谱评论报告

    Report::where('offender_id','=',Auth::check()->id)
    ->where('reportable_type','=','RecipeComment')
    ->get();
    

    按用户

    的类型计算攻击次数
    Report::where('offender_id','=',Auth::check()->id)
    ->grouBy('reportable_type')
    ->select(Db::raw('count(*)'),'reportable_type')
    ->get();