У меня есть модель 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) .