简体   繁体   English

Laravel:多对多共享表

[英]Laravel: many-to-many with shared table

I have Locations model which hasMany Employees -- similarly Employees belongsTo Locations 我有一个具有许多Employees Locations模型-类似地, Employees属于Locations

This is nice and works well, but then I looked at adding PhoneNumbers . 很好,效果很好,但是后来我看了添加PhoneNumbers Either a Location or an Employee could have a phone number (office numbers versus personal numbers) 无论LocationEmployee可能有一个电话号码(办公室号码与个人号码)

Logically: 从逻辑上讲:

Locations hasMany PhoneNumbers (multiple office lines) and Employees hasMany PhoneNumbers (home / cell ?) Locations的hasMany PhoneNumbers (多个办公室线)和Employees的hasMany PhoneNumbers (家庭/细胞?)

However when you create a hasMany relationship like this in Laravel it adds a field to the PhoneNumbers table. 但是,当您在Laravel中创建hasMany关系时,会向PhoneNumbers表中添加一个字段。 So we now have two fields: location_id and employee_id 因此,我们现在有两个字段: location_idemployee_id

I can get this to work if I make location_id and employee_id nullable, like so: 如果我将location_idemployee_id可空,则可以使它正常工作,如下所示:

+----+--------------+-------------+-------------+
| id |    number    | location_id | employee_id |
+----+--------------+-------------+-------------+
|  1 | 800-555-0123 |      1      |     null    |
|  2 | 800-555-0124 |      1      |     null    |
|  3 | 800-555-0125 |      1      |     null    |
|  4 | 859-555-0199 |     null    |       1     |
                     ...

However this doesn't scale very well if I add new entities that can possess phone numbers (customers? job applicants? suppliers?) 但是,如果我添加可以拥有电话号码的新实体(客户,求职者或供应商?),这将不能很好地扩展。

How can I create multiple separate many-to-many relationships with the same secondary table? 如何使用同一个辅助表创建多个单独的多对多关系?

Note: In this example I could just create a phone_number field on each individual tables ( locations.phone_number , employees.phone_number , etc) however I wish to avoid this for two reasons: 注意:在此示例中,我只可以在每个表上创建一个phone_number字段( locations.phone_numberemployees.phone_number等),但是出于两个原因,我希望避免这种情况:

  1. Data integrity (if all phone numbers are in one common table it's easy to verify duplicate phone numbers are not entered) 数据完整性(如果所有电话号码都在一个公用表中,则很容易验证未输入重复的电话号码)
  2. Binding to more complex models (replace PhoneNumber with Image and now you have a lot more data to deal with) 绑定到更复杂的模型(用Image替换PhoneNumber ,现在您有更多数据要处理)

You're looking for Laravel's polymorphic relationship. 您正在寻找Laravel的多态关系。 Instead of creating a new field for each related table, you have two fields: related id and related type. 您有两个字段,而不是为每个相关表创建一个新字段:相关ID和相关类型。

On both your Location and Employee model, add the following relationship: 在“位置”和“员工”模型上,添加以下关系:

public function phones()
{
    return $this->morphMany('PhoneNumber', 'phonable');
}

On your PhoneNumber model, add the following relationship: 在您的PhoneNumber模型上,添加以下关系:

public function phonable()
{
    return $this->morphTo();
}

On your phone_numbers table, add two new fields: phonable_type and phonable_id. 在phone_numbers表上,添加两个新字段:phonable_type和phonable_id。 In a migration, these fields are added with the morphs() method: $table->morphs('phonable'); 在迁移中,这些字段使用$table->morphs('phonable'); morphs()方法添加: $table->morphs('phonable');

Once everything is setup, your data would look like this: 一切设置完成后,您的数据将如下所示:

+----+--------------+-------------+---------------+
| id |    number    | phonable_id | phonable_type |
+----+--------------+-------------+---------------+
|  1 | 800-555-0123 |      1      |    Location   |
|  2 | 800-555-0124 |      1      |    Location   |
|  3 | 800-555-0125 |      1      |    Location   |
|  4 | 859-555-0199 |      1      |    Employee   |
                     ...

With this setup, you can make any model you want phonable just by adding a morphOne() or morphMany() relationship to it. 通过此设置,只需phonable添加morphOne()morphMany()关系,就可以使任何模型成为可phonable模型。

Additionally, the relationship attributes will generate the correct model related to the type. 此外,关系属性将生成与类型相关的正确模型。 Given the data above: 鉴于以上数据:

var_dump(PhoneNumber::find(1)->phonable); // will dump Location object
var_dump(PhoneNumber::find(4)->phonable); // will dump Employee object

The documentation on polymorphic relationships can be found here (4.2) or here (5.0) . 有关多态关系的文档可在此处(4.2)此处(5.0)找到

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM