У меня есть модель Locations
которой есть много Employees
– аналогично Employees
местным местам
Это хорошо и хорошо работает, но потом я посмотрел на добавление PhoneNumbers
. Либо Location
либо Employee
могут иметь номер телефона (служебные номера и личные номера)
Логически:
Locations
hasMany PhoneNumbers
(несколько офисных линий) и Employees
hasMany PhoneNumbers
(home / cell?)
Однако, когда вы создаете отношения hasMany, подобные этому в Laravel, он добавляет поле в таблицу PhoneNumbers
. Итак, теперь у нас есть два поля: location_id
и employee_id
Я могу заставить это работать, если я сделаю location_id
и employee_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 | ...
Однако это не очень хорошо масштабируется, если я добавляю новые объекты, которые могут иметь номера телефонов (клиенты? Кандидаты на работу? Поставщики?)
Как я могу создать несколько отдельных отношений «многие ко многим» с одной и той же вторичной таблицей?
Примечание. В этом примере я мог бы просто создать поле phone_number
на каждой отдельной таблице ( locations.phone_number
, employees.phone_number
и т. Д.), Однако я хочу избежать этого по двум причинам:
PhoneNumber
на Image
и теперь у вас есть гораздо больше данных для решения) Вы ищете полиморфные отношения Ларавеля. Вместо создания нового поля для каждой связанной таблицы вы имеете два поля: связанный идентификатор и родственный тип.
В вашей модели Location и Employee добавьте следующее соотношение:
public function phones() { return $this->morphMany('PhoneNumber', 'phonable'); }
В вашей модели PhoneNumber добавьте следующее соотношение:
public function phonable() { return $this->morphTo(); }
В таблице phone_numbers добавьте два новых поля: phonable_type и phonable_id. При миграции эти поля добавляются с помощью метода $table->morphs('phonable');
morphs()
: $table->morphs('phonable');
Когда все будет установлено, ваши данные будут выглядеть так:
+----+--------------+-------------+---------------+ | 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 | ...
С помощью этой установки вы можете сделать любую модель, которую хотите phonable
только добавив к ней отношение morphOne()
или morphMany()
.
Кроме того, атрибуты отношений будут генерировать правильную модель, связанную с типом. Учитывая приведенные выше данные:
var_dump(PhoneNumber::find(1)->phonable); // will dump Location object var_dump(PhoneNumber::find(4)->phonable); // will dump Employee object
Документацию по полиморфным отношениям можно найти здесь (4.2) или здесь (5.0) .