Laravel关系:hasMany通过数据透视表上的模型

时间:2018-02-21 16:47:26

标签: laravel orm eloquent

我在Laravel中有3个模型:

Item ModifierGroup Modifier

Item通过中间表可以有多个ModifierGroups

public function modifierGroups()
    {
        return $this->belongsToMany(
            'App\ModifierGroup', 
            'menu_item_modifiers', 
            'item_id', 
            'group_id'
        )->using('App\MenuItemModifier')
         ->orderBy('position', 'ASC')
         ->withPivot('position');
    }

ModifierGroup有许多Modifiers

public function modifiers()
    {
        return $this->hasMany(
            'App\Modifier', 
            'group_id', 
            'id'
        )->orderBy('position', 'ASC');
    }

我的问题是,Item是否可以通过Modifiers(及其支点)获得ModifierGroup的功能? HasManyThrough似乎不适合所涉及的数据透视表或是否适用?

2 个答案:

答案 0 :(得分:0)

使用数据透视表可以解决此问题,但不能像使用它们那样解决。我假设你有三个表 - 每个表与你的模型相关联(ItemModifierGroupModifier),你没有设置透视功能,因为你实际上没有透视表。为此,您需要一个表格将ItemModifierGroups相关联,另一个表格将ModifierGroupsModifier相关联。

首先,让我们使用Artisan创建表格:

php artisan generate:pivot Item ModifierGroup

现在,我们有一个名为item_modifier_group的表(我相信?)。该表应该有两列,item_id和modifier_group_id。这些是Eloquent用于连接items和modifier_groups表的键。现在,在我们的查询中,我们可以使用以下查询访问和项目的修改器组:

public function modifierGroups()
{
    return $this->belongsToMany('App\ModifierGroup');
}

这意味着当您致电$item->modifierGroups()时,您将获得ID为$item->id的所有修改器组的集合。

然后可以针对ModifierGroupsModifiers关系重复此过程:

php artisan generate:pivot ModifierGroup Modifiers

现在在ModifierGroup模型中定义修饰符方法:

public function modifiers()
{
    return $this->belongsToMany('App\Modifier');
}

现在我们设置了数据透视表,并且我们的关系在一个方向上定义(只需向模型添加类似的方法以通过修改器获取项目)

馅饼的最后一块是Eager Loading(太神奇了)。 获取项目,通过适当的组修改器,如下所示:

Item::with('modifierGroups.modifiers')->findOrFail('id');

现在还有其他方法可以解决这个问题,有些甚至可能更有效,但这样做的巨大好处是灵活性。您现在可以使用数据透视表连接Items,ModifierGroup和Modifiers,并使用简单的预先加载的查询,可以获得您认为必要的任何集合组合。希望这有帮助!这绝对是我在这里写过的最长的解决方案......

为了将来阅读,我建议:

Eager Loading - 嵌套的渴望加载

Defining Relationships - 多对多

答案 1 :(得分:0)

可以通过“跳过” BelongsToMany表来建立ModifierGroup关系:

public function modifiers() {
    return $this->belongsToMany(
        'App\Modifier',
        'menu_item_modifiers',
        'item_id',
        'group_id',
        null,
        'group_id'
    );
}