拉拉维尔:排序多对多关系


Laravel: ordering a many-many relation

我在成分和食谱之间有一个多对多关系,有一个数据透视表(ingredient_recipe)。

我想按有多少食谱订购成分。例如,如果我在 2 个食谱中使用盐,在 3 个食谱中使用肉,我会先吃肉然后再吃盐。

这就是我所拥有的。它可以工作,但它没有正确排序,即使直接在我的数据库上执行的结果查询按预期工作,所以 Laravel 正在内部做一些事情,我猜。

//Ingredient model
public function recipesCount()
{
    return $this->belongsToMany('Recipe')->selectRaw('count(ingredient_recipe.recipe_id) as aggregate')->orderBy('aggregate', 'desc')->groupBy('ingredient_recipe.ingredient_id');
}
public function getRecipesCountAttribute()
{
    if ( ! array_key_exists('recipesCount', $this->relations)) $this->load('recipesCount');
    $related = $this->getRelation('recipesCount')->first();
    return ($related) ? $related->aggregate : 0;
}
//controller
$ingredients = Ingredient::with('recipesCount')->whereHas('recipes', function($q)
                    {
                            $q->where('user_id', Auth::id());
                    })->take(5)->get();
//outputting the last query here and executing it on my db returns correctly ordered results.

我该如何解决它?

为了order by相关的表,您需要join .没有任何办法通过急切加载来实现这一点。

Ingredient::with('recipesCount')
    ->join('ingredient_recipe as ir', 'ir.ingredient_id', '=', 'ingredients.id')
    ->join('recipes as r', function ($j) {
        $j->on('r.id', '=', 'ir.recipe_id')
          ->where('r.user_id', '=', Auth::id());
    })
    ->orderByRaw('count(r.id) desc')
    ->groupBy('ingredients.id')
    ->take(5)
    ->get(['ingredients.*']);

不再需要whereHas,因为inner joins会为你完成这项工作。