2016-03-24 86 views
21

我很好奇为什么hasMany的Eloquent关系与belongsToMany有不同的签名。特别是自定义连接表名称 - 对于给定的Comment属于多个Role s且给定的Role将具有多个Comment的系统,我想将关系存储在名为my_custom_join_table的表中,并将键设置为comment_keyrole_keyhasMany vs belongsToMany在laravel 5.x

return $this->belongsToMany('App\Role', 'my_custom_join_table', 'comment_key', 'role_key'); // works 

但在倒数,我不能定义自定义表(至少在文档不提到它):如果我有一个Role对象

return $this->hasMany('App\Comment', 'comment_key', 'role_key'); 

hasManyComments,但我使用非标准表名来存储这种关系,为什么我可以使用这种非标准表进行一种方式而不是另一种?

+0

双向的逆多到多的关系是许多对多,而不是一个一对多。学说有一个[所有关系秩序的很好的介绍](http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-many-bidirectional )及其实现。 – bishop

+0

官方文档也有一个很好的关于雄辩关系的写法https://laravel.com/docs/5.2/eloquent-relationships – user3158900

回答

64

hasMany用于One To Many的关系,而belongsToMany指的是Many To Many的关系。它们都是不同的关系类型,每个都需要不同的数据库结构 - 因此它们采用不同的参数。

关键区别在于,在一对多关系中,您只需要与相关模型对应的两个数据库表。这是因为对关系的引用是存储在自有模型的表本身上。例如,您可能有Country型号和City型号。一个国家有许多城市。但是,每个城市只存在于一个国家。因此,您可以在城市模型(如country_id或类似的东西)上存储该国家

然而,一个多对多的关系需要第三数据库表,称为透视表。数据透视表存储对两个模型的引用,您可以将其声明为关系声明中的第二个参数。例如,假设您有City型号,并且您还有一个Car型号。你想要一段关系来展示人们在每个城市驾车的类型。那么,在一个城市里人们会开车很多不同类型的车。但是,如果你看一辆车类型,你也会知道它可以驱动很多不同的城市。因此,在任何一个模型上都不可能存储city_idcar_id,因为每个模型都可能有多个模型。因此,您将这些引用放在数据透视表中。

作为一个经验法则,如果你使用一个belongsToMany关系,它可以与另一belongsToMany关系配对,意味着你有第三个数据透视表。如果您使用hasMany关系,它可以只有belongsTo关系配对,并且不需要额外的数据库表。

在你的例子中,你只需要将逆关系变成belongsToMany并再次添加自定义表格以及外键和本地键(颠倒另一个模型的顺序)。

+1

简单,完整,高效 –

+0

非常干净和有用的解释! – Andy

+0

完美解释 –

13

试着用文字和图形来理解。

  1. 一对一(hasOne)的关系:

    • 用户已(可以有)一个配置文件。所以,一个配置文件属于一个用户。
  2. 一对多(的hasMany):

    • 的用户有很多(可以有很多)的文章。所以,很多文章属于一个用户。
  3. 多对多(BelongsToMany):

    • 用户可以属于多个论坛。所以,一个论坛属于许多用户。

    RelationShip

+0

在hasOne/belongsTo的情况下,我想hasOne会规定哪个表将保存对相关表的引用(在这种情况下,用户表有一个profile_id)? – Lunfel