与雄辩的四对多关系

时间:2014-01-18 07:50:45

标签: php laravel laravel-4 relationship eloquent

我正在使用Laravels Eloquent ORM,我遇到了一个特殊关系的小问题。让我们假设我有下表:

Recipe:
   id | ... | ingredient1 | ingredient2 | ingredient3 | ingredient4

每个食谱都有4个成分,我从这个特定格式的外部来源获取数据,这就是为什么我将成分作为列而不是正常的多对多关系。

我可以将它们设置为4个一对多关系,但我希望能够写出$ingredient->usedInRecipes()->get()
 使用4个一对多关系,我必须写$ingredient->usedInRecipesAsIngredient1()->get(),[...],$ingredient->usedInRecipesAsIngredient4()->get()并在之后合并它们,这将导致4个查询。

如果您在查询数据库之前知道加入这些内容的好方法,或者如何使4对多关系工作,请回答!

2 个答案:

答案 0 :(得分:1)

从问题我无法判断你是否已经尝试过这个问题,尽管我认为你只需要使用一对多关系。

每种成分可能都有一组共同的属性,可以在一个表ingredients中处理。

id    name        created_at                updated_at
1     Paprika     01/01/1970 00:00:00       01/01/1970 00:00:00
1     Rosemary    01/01/1970 00:00:00       01/01/1970 00:00:00
1     Basil       01/01/1970 00:00:00       01/01/1970 00:00:00
1     Oregano     01/01/1970 00:00:00       01/01/1970 00:00:00

然后是你的recipes

id    name        created_at                updated_at
1     Herb Soup   01/01/1970 00:00:00       01/01/1970 00:00:00

要保存关系,数据透视表ingredient_recipe

id    recipe_id   ingredient_id
1     1           1
2     1           2
3     1           3
4     1           4

现在您所需要的只是belongsToManyRecipe模型上的Ingredient关系。

如果您愿意,您可以编写保护措施以确保一个食谱只与成分有4种关系,但要保持简单:

Recipe::with('ingredients')->get();

将检索所有成分和食谱。

You can read more about this relationship in the documentation here.

没有Pivots

如果您在ingredient_1表格中保留了ingredient_2recipes等列,则可以向Recipe模型添加类似的内容。

public function scopeGetWithIngredients($query)
{
    $query->leftJoin('ingredients i1', 'recipes.ingredient_1', '=', 'i1.id')
          ->leftJoin('ingredients i2', 'recipes.ingredient_2', '=', 'i2.id')
          ->leftJoin('ingredients i3', 'recipes.ingredient_3', '=', 'i3.id')
          ->leftJoin('ingredients i4', 'recipes.ingredient_4', '=', 'i4.id')
          ->select('recipes.name', 'i1.name AS ing_1', 'i2.name AS ing_2');
}

然后您可以使用

获取模型中的成分
Recipe::getWithIngredients();

答案 1 :(得分:0)

我找到了一个似乎适用于我所有用例的解决方案。

在配方模型中,我将4种成分定义为一对多关系,并制作了两个辅助范围函数。

class Recipe extends Eloquent { 
    public function ingredient1()
        { return $this->belongsTo('Ingredient', 'ingredient1'); }
    public function ingredient2()
        { return $this->belongsTo('Ingredient', 'ingredient2'); }
    public function ingredient3()
        { return $this->belongsTo('Ingredient', 'ingredient3'); }
    public function ingredient4()
        { return $this->belongsTo('Ingredient', 'ingredient4'); }

    public function scopeHasIngredient( $query, Ingredient $ingredient ) {
        return $query->  where( 'ingredient1', '=', $ingredient->id )
                     ->orWhere( 'ingredient2', '=', $ingredient->id )
                     ->orWhere( 'ingredient3', '=', $ingredient->id )
                     ->orWhere( 'ingredient4', '=', $ingredient->id );
    }

    public function scopeWithIngredients( $query ) {
        return $query->with('ingredient1', 'ingredient2',
                            'ingredient3', 'ingredient4');
    }
}

class Ingredient extends Eloquent {
    public function ingredientForRecipes() {
        return Recipe::hasIngredient( $this )->withIngredients();
    }
}

要获取成分的所有食谱,我现在可以致电$ingredient->ingredientForRecipes()->get()并使用这些成分而无需额外查询。