Отношения в Laravel (Eloquent Relationships) относительно просты для понимания, но некоторые люди могут растеряться без наглядных рисунков, показывающих то, что нельзя передать словами. Одна из сложностей документации Laravel заключается в том, что она не иллюстрирована. Поняв это, я решил сделать собственные иллюстрации и поделиться ими с вами.


Один к Одному (One to One)

Отношения "Один к Одному" очень просты: одна запись связана с другой. Одна из записей - это "Родитель", а другая - "Потомок" (Дочерняя). Они определяются методами hasOne() и belongsTo(), соответственно.

Дочерняя модель имеет указатель на Родителя. Удаление родительской модели оставит дочернюю модель сиротой (orphaned).


Один ко Многим (One to Many)

Отношение "Один ко Многим" - это то же самое, что и отношение "Один к Одному", но запись "Родитель" может иметь много "Потомков", а множество "Потомков" могут указывать на одного "Родителя". Отличие так же в том, что здесь используется метод hasMany().

Когда вы запрашиваете отношение, то получаете коллекцию связанных записей, даже если имеется всего одна дочерняя запись.


Многие ко Многим (Many to Many)

Отношение "Многие ко Многим" понять сложнее. По сути, запись может быть связана со множеством других записей, и наоборот.

Сводная таблица (pivot table) - вот что делает это возможным. Она связывает одну запись из одной таблицы с другой, столько раз, сколько требуется. Если сводная таблица исчезает, то обе таблицы становятся несвязанными, поскольку информация об их связи содержится только в этой таблице.

Например, в сводной таблице может быть три записи, указывающие на одну и ту же запись foo.id = 2, но каждая из них указывает на bar.id = 1, bar.id = 2 и bar.id = 4. То же самое может происходить в обратном порядке.


К Одному Через (Has One Through)

Отношение "К Одному Через" получает другую запись, используя промежуточную таблицу, которая в этом случае работает почти как сводная таблица - каждая запись содержит ссылку на запись bar и запись quz, соединяя их.

Чтобы лучше представить, как это работает, я возьму тот же пример из документации Laravel и нарисую базу данных, чтобы вы могли понять, как соединяются таблицы:

Как видите, SQL-запрос будет использовать таблицу users для доступа к записям таблицы history.


Ко Многим Через (Has Many Through)

Отношения "Ко Многим Через" работают так же, как "К Одному Через", но разница в том, что одна запись может иметь много далеких отношений.

Давайте снова возьмем пример из документации, где предлагается способ взять множество сообщений из одной страны. Как вы понимаете, таблица users действует как сводная таблица.


Полиморфные Один к Одному (One to One Polymorphic)

Полиморфные отношения "Один к Одному" такие же, как и обычные "Один к Одному", но Дочерняя запись может указывать на разные таблицы, следовательно, на разные Родительские Модели. Для этого нужны два столбца: для таблицы и идентификатора записи.

Метод morphTo() находится в Дочерней таблице, а morphOne() - в Родительских Моделях. Другими словами, этот тип отношений позволяет Потомку иметь множество типов Родителей - звучит странно, но необходимо это отметить.


Полиморфные Один ко Многим (One to Many Polymorphic)

Это то же самое, что "Один ко Многим", но в этом примере модели foo и quz могут взять множество записей модели bar. Как вы видите, модели, использующие метод morphMany() могут рассматриваться как Родители и могут иметь множество Потомков, но разница в том, что эти Родители могут быть любого типа.

Это связано с тем, что несколько записей в Дочерней таблице могут указывать на одного и того же родителя.


Полиморфные Многие ко Многим (Many to Many Polymorphic)

То же, что "Многие ко Многим", где сводная таблица отвечает за раскрытие отношений. Для ясности: Дочерние Модели больше не ограничены одним Родительским отношением, а любым, который может это принять.