Laravel:订购多对多关系

Laravel: ordering a many-many relation

我在 Ingredient 和 Recipe 之间有一个多对多的关系,有一个支点 table (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 相关 table 你需要 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 会为您完成这项工作。