Laravel 雄辩的多对多模型

Posted

技术标签:

【中文标题】Laravel 雄辩的多对多模型【英文标题】:Laravel eloquent many to many to many model 【发布时间】:2014-03-17 14:28:51 【问题描述】:

我在 laravel 4 中做一个项目,我已经停下来了。

任务表:

task_id (PK)
task_title

测量表:

measure_id (PK)
measure_title

例程表:

routine_id (PK)
date
time
value
emp_id (FK)

emps 表:

emp_id (PK)
first_name
last_name
user_name
email
user_type

现在我很困惑的是如何用雄辩的方式模拟这些关系,因为我似乎无法弄清楚。在phpmyadmin DB 中,我目前有两个表将任务和测量值连接到具有task_routine 的例程:task_id (PK)routine_id (PK)measure_routinemeasure_id (PK)routine_id(PK)

希望在我写这篇文章的时候,我脑海中的声音就这么清晰,感谢您的帮助!

【问题讨论】:

你的问题到底是什么?您希望如何在哪些表之间建立关系? 是的 - 您只是在寻找设置方法,还是寻找将任务直接连接到度量的方法? 查看本教程...vegibit.com/many-to-many-relationships-in-laravel 【参考方案1】:

首先在所有表格中将PK 字段从*_id 更改为id。如果您想为一个表与另一个表建立关系,那么约定是,您应该使用父表的name_id(名称应为单数形式)在子表中保留一个外键,例如,构建empsroutines 表之间的关系,您应该在 routines 表中使用 emp_id 外键,并且您的 emps 表应该包含 id PK。因此,您的 emps 表是父表,routinesemps 的子表,两个表中的记录应该是这样的(可以使用自定义约定):

emps(父):

id (pk) | first_name | more fields ...
    1   | Mr         | ...
    2   | Miss       | ...  
    3   | Mrs        | ...  

routines(子):

id (pk) | emp_id (FK) | more fields ...
    1   |    1        | ...            - Child of emps table's first record
    2   |    3        | ...            - Child of emps table's third record
    3   |    3        | ...            - Child of emps table's third record

这里,emps 表中的每个id 都用作emp_id 字段中routines 表中的外键。所以,emps 表在routines 表中有三个相关记录,emps 表中的第一条记录与routines 表中的第一条记录和emps 表中的第三条记录相关(id 为3 ) 在routines 表中有两条相关记录(第二条和第三条),因为两条记录都包含emps 表在emp_id 字段中的第三条记录的id 3

现在使用 Laravel 建立关系:

如果您的父表在子表中只有一个相关表,则使用one-to-one,例如,如果emps 表中id 为1(第一条记录)的记录在routines 中只有一个相关记录使用emp_id 字段的表,其值为1,如果它不能在routines 表中的多个记录中,则它是one-to-one 关系,在上面给出的示例记录中不是one-to-one 关系,因为在routines 表中,有两条记录与emps 表中的id/pk 相同,因此它转到one-to-many 关系,因此可以将其读取为emps 记录中有许多routines。要建立one-to-many 关系,我们可以使用:

class Emp extends Eloquent 
    public function routines()
    
        return $this->hasMany('Routine');
    

Routine 模型:

class Routine extends Eloquent 
    public function emp()
    
        return $this->belongsTo('Emp');
    

one-to-many 关系中,父表可能包含多个具有相同id 的子记录,但如果子表中的记录也有许多父记录,则它应该是many-to-many 关系。例如,如果我们想在例程表中建立这样的关系(不可能两次使用相同的主键):

id (pk) | emp_id (FK) | more fields ...
    1   |    1        | ...            
    2   |    2        | ...            - Record 2(id) has parent 2(emp_id)
    2   |    3        | ...            - Record 2(id) has also parent 3(emp_id)

在这种情况下,这是一个many-to-many 关系,不可能在一个表中使用相同的id/PK 两次,因此我们需要使用第三个表在emps 表和routines 表之间建立many-to-many 关系表(称为pivot 表)来维护many-to-many 关系。所以,它看起来像下表:

表名应该是emp_routine,但还有其他方法可以使用 不同的名称,但遵循此约定。

emp_routine数据透视表:

id (pk) | emp_id (id/PK of emps) | routine_id (id/PK of routines) | more fields ...
    1   |   1                    |    1                           | ...
    2   |   2                    |    1                           | ...
    3   |   1                    |    2                           | ...

这里,父母和孩子在两个表中都有多个相关记录,并且这个pivot 表维护了这种关系。

要使用Laravel 建立关系,我们可以使用:

class Emp extends Eloquent 
    public function routines()
    
        return $this->belongsToMany('Routine');
    

Routine 模型:

class Routine extends Eloquent 
    public function emp()
    
        return $this->belongsToMany('Emp');
    

在这种情况下,我们不需要 routines 表中的外键字段 (emp_id),因为我们使用数据透视表来维护关系,但如果它存在,则不会有问题。

应该注意的是,每当您在父表中插入/更新任何记录时,您还必须在数据透视表中插入/更新关系数据,Laravel 为这些提供了有用的方法,所以check the manual (relationship)。

【讨论】:

嘿,感谢您的冗长回答,它对我理解它的工作原理有很大帮助。如果您示例中的 emp 表与两个表具有多对多关系,这将如何工作?只需为所有三个表扩展 Eloquent 并在两个表上对 emp 运行 belongsToMany 函数,然后对两个表运行emp? 是的,对于many-to-many 关系,请使用每个模型中的belongsToMany 并使用pivot 表。 感谢所有帮助,非常感谢!

以上是关于Laravel 雄辩的多对多模型的主要内容,如果未能解决你的问题,请参考以下文章

雄辩的多对多对多 - 如何轻松加载远距离关系

如何从雄辩关系中的第三个表中获取数据雄辩的多对多关系

两个多对多相关表之间的Laravel雄辩关系

Laravel 多对多中的雄辩关系通过

雄辩的多对多关系总是空的

Laravel 同一模型上的多对多