Красноречивые отношения Laravel PHPфреймворк для вебмастеров

Красноречивый: Отношения.

Введение.

Таблицы базы данных часто связаны друг с другом. Например, сообщение в блоге может содержать много комментариев или заказ может быть связан с пользователем, который его разместил. Eloquent упрощает управление этими отношениями и работу с ними, а также поддерживает множество общих отношений:

Один к одному ко многим Многие ко многим имеет один сквозной имеет много через один к одному (полиморфный) один ко многим (полиморфный) многие ко многим (полиморфный)

Определение отношений.

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

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

Один к одному.

Отношения «один к одному» — это очень простой тип взаимоотношений с базой данных. Например, модель пользователя может быть связана с одной моделью телефона. Чтобы определить эту взаимосвязь, мы поместим метод phone в модель User. Метод phone должен вызывать метод hasOne и возвращать его результат. Метод hasOne доступен для вашей модели через ее базовый класс Illuminate \ Database \ Eloquent \ Model:

Первым аргументом, передаваемым методу hasOne, является имя соответствующего класса модели. Как только связь определена, мы можем получить связанную запись, используя динамические свойства Eloquent. Динамические свойства позволяют получить доступ к методам отношений, как если бы они были свойствами, определенными в модели:

Eloquent определяет внешний ключ отношения на основе имени родительской модели. В этом случае автоматически предполагается, что модель Phone имеет внешний ключ user_id. Если вы хотите переопределить это соглашение, вы можете передать второй аргумент методу hasOne:

Кроме того, Eloquent предполагает, что внешний ключ должен иметь значение, соответствующее столбцу первичного ключа родительского элемента. Другими словами, Eloquent будет искать значение столбца идентификатора пользователя в столбце user_id записи телефона. Если вы хотите, чтобы отношение использовало значение первичного ключа, отличное от id или свойства вашей модели $ primaryKey, вы можете передать третий аргумент методу hasOne:

Определение обратной связи.

Итак, мы можем получить доступ к модели телефона из нашей модели пользователя. Затем давайте определим отношения в модели Phone, которые позволят нам получить доступ к пользователю, которому принадлежит телефон. Мы можем определить инверсию отношения hasOne с помощью метода ownTo:

При вызове пользовательского метода Eloquent попытается найти модель User, идентификатор которой соответствует столбцу user_id в модели Phone..

Eloquent определяет имя внешнего ключа, исследуя имя метода отношения и добавляя к имени метода суффикс _id. Итак, в этом случае Eloquent предполагает, что модель Phone имеет столбец user_id. Однако, если внешний ключ в модели Phone не является user_id, вы можете передать имя настраиваемого ключа в качестве второго аргумента метода ownTo:

Если родительская модель не использует id в качестве первичного ключа или вы хотите найти связанную модель, используя другой столбец, вы можете передать третий аргумент методу ownTo, указав настраиваемый ключ родительской таблицы:

Один ко многим.

Отношение «один ко многим» используется для определения отношений, в которых одна модель является родительской для одной или нескольких дочерних моделей. Например, сообщение в блоге может содержать бесконечное количество комментариев. Как и все другие отношения Eloquent, отношения «один ко многим» определяются путем определения метода в вашей модели Eloquent:

Помните, что Eloquent автоматически определит правильный столбец внешнего ключа для модели комментариев. По соглашению, Eloquent возьмет "змея чехол" имя родительской модели и суффикс _id. Итак, в этом примере Eloquent предполагает, что столбец внешнего ключа в модели комментариев — post_id. .

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

Поскольку все отношения также служат в качестве построителей запросов, вы можете добавить дополнительные ограничения в запрос отношения, вызвав метод комментариев и продолжая связывать условия с запросом:

Как и в случае с методом hasOne, вы также можете переопределить внешние и локальные ключи, передав дополнительные аргументы методу hasMany:

Один ко многим (обратный) / принадлежит.

Теперь, когда мы можем получить доступ ко всем комментариям поста, давайте определим отношение, чтобы разрешить комментарию доступ к его родительскому посту. Чтобы определить инверсию отношения hasMany, определите метод отношения в дочерней модели, который вызывает метод ownTo:

После определения отношения мы можем получить родительский пост комментария, открыв его. "свойство динамического отношения":

В приведенном выше примере Eloquent попытается найти модель публикации, идентификатор которой соответствует столбцу post_id в модели комментариев..

Eloquent определяет имя внешнего ключа по умолчанию, проверяя имя метода отношения и добавляя к имени метода суффикс _, за которым следует имя столбца первичного ключа родительской модели. Итак, в этом примере Eloquent предполагает, что внешний ключ модели Post в таблице комментариев равен post_id. .

Однако, если внешний ключ для ваших отношений не соответствует этим соглашениям, вы можете передать настраиваемое имя внешнего ключа в качестве второго аргумента метода ownTo:

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

Модели по умолчанию.

Отношения ownTo, hasOne, hasOneThrough и morphOne позволяют определить модель по умолчанию, которая будет возвращена, если данное отношение равно null. Этот шаблон часто называют шаблоном нулевого объекта и может помочь удалить условные проверки в вашем коде. В следующем примере отношение пользователя вернет пустую модель App \ Models \ User, если к модели Post не привязан пользователь:

Чтобы заполнить модель по умолчанию атрибутами, вы можете передать массив или закрытие методу withDefault:

Имеет один сквозной.

В "имеет сквозной" Relationship определяют взаимно-однозначные отношения с другой моделью. Однако это отношение указывает на то, что модель объявления может быть сопоставлена ​​с одним экземпляром другой модели, пройдя через третью модель..

Например, в приложении автомастерской каждая модель механика может быть связана с одной моделью автомобиля, а каждая модель автомобиля может быть связана с одной моделью владельца. В то время как механик и владелец не имеют прямых отношений в базе данных, механик может получить доступ к владельцу через модель автомобиля. Давайте посмотрим на таблицы, необходимые для определения этой связи:

Теперь, когда мы изучили структуру таблицы для отношений, давайте определим отношения в модели Mechanic:

Первый аргумент, переданный методу hasOneThrough, — это имя последней модели, к которой мы хотим получить доступ, а второй аргумент — это имя промежуточной модели..

Основные условные обозначения.

При выполнении запросов отношения будут использоваться типичные соглашения о внешнем ключе Eloquent. Если вы хотите настроить ключи отношения, вы можете передать их в качестве третьего и четвертого аргументов методу hasOneThrough. Третий аргумент — это имя внешнего ключа промежуточной модели. Четвертый аргумент — это имя внешнего ключа окончательной модели. Пятый аргумент — это локальный ключ, а шестой аргумент — это локальный ключ промежуточной модели:

Имеет много сквозных.

В "имеет-много-сквозной" Relationship предоставляют удобный способ доступа к удаленным отношениям через промежуточные отношения. Например, предположим, что мы создаем платформу развертывания, такую ​​как Laravel Vapor. Модель проекта может получить доступ ко многим моделям развертывания через промежуточную модель среды. Используя этот пример, вы можете легко собрать все развертывания для данной среды. Давайте посмотрим на таблицы, необходимые для определения этой связи:

Теперь, когда мы изучили структуру таблицы для связи, давайте определим связь в модели Project:

Первый аргумент, переданный методу hasManyThrough, — это имя последней модели, к которой мы хотим получить доступ, а второй аргумент — это имя промежуточной модели..

Хотя таблица модели развертывания не содержит столбца project_id, отношение hasManyThrough обеспечивает доступ к развертываниям проекта через $ project.->развертывания. Чтобы получить эти модели, Eloquent проверяет столбец project_id в таблице промежуточной модели Environment. После нахождения соответствующих идентификаторов среды они используются для запроса таблицы модели развертывания..

Основные условные обозначения.

При выполнении запросов отношения будут использоваться типичные соглашения о внешнем ключе Eloquent. Если вы хотите настроить ключи отношения, вы можете передать их в качестве третьего и четвертого аргументов методу hasManyThrough. Третий аргумент — это имя внешнего ключа промежуточной модели. Четвертый аргумент — это имя внешнего ключа окончательной модели. Пятый аргумент — это локальный ключ, а шестой аргумент — это локальный ключ промежуточной модели:

Отношения многие ко многим.

Отношения «многие ко многим» немного сложнее, чем отношения hasOne и hasMany. Примером отношения «многие ко многим» является пользователь, у которого много ролей, и эти роли также используются другими пользователями в приложении. Например, пользователю может быть назначена роль "Автор" и "редактор"; однако эти роли также могут быть назначены другим пользователям. Итак, у пользователя много ролей, а у роли много пользователей..

Структура таблицы.

Для определения этой связи необходимы три таблицы базы данных: пользователи, роли и role_user. Таблица role_user является производной от алфавитного порядка имен связанных моделей и содержит столбцы user_id и role_id. Эта таблица используется как промежуточная таблица, связывающая пользователей и роли..

Помните, поскольку роль может принадлежать многим пользователям, мы не можем просто разместить столбец user_id в таблице ролей. Это означало бы, что роль могла принадлежать только одному пользователю. Чтобы обеспечить поддержку ролей, назначаемых нескольким пользователям, необходима таблица role_user. Мы можем резюмировать структуру таблицы отношений следующим образом:

Структура модели.

Отношения «многие ко многим» определяются путем написания метода, который возвращает результат метода ownToMany. Метод ownToMany предоставляется базовым классом Illuminate \ Database \ Eloquent \ Model, который используется всеми моделями Eloquent вашего приложения. Например, давайте определим метод ролей в нашей модели User. Первым аргументом, передаваемым этому методу, является имя соответствующего класса модели:

После определения отношения вы можете получить доступ к ролям пользователя, используя свойство динамического отношения ролей:

Поскольку все отношения также служат в качестве построителей запросов, вы можете добавить дополнительные ограничения в запрос отношений, вызвав метод ролей и продолжив связывать условия с запросом:

Чтобы определить имя таблицы промежуточной таблицы отношения, Eloquent соединит имена двух связанных моделей в алфавитном порядке. Однако вы можете изменить это соглашение. Вы можете сделать это, передав второй аргумент методу ownToMany:

Помимо настройки имени промежуточной таблицы, вы также можете настроить имена столбцов ключей в таблице, передав дополнительные аргументы методу ownToMany. Третий аргумент — это имя внешнего ключа модели, для которой вы определяете отношение, а четвертый аргумент — это имя внешнего ключа модели, к которой вы присоединяетесь:

Определение обратной связи.

Чтобы определить "обратный" отношения «многие ко многим» следует определить метод в связанной модели, который также возвращает результат метода ownToMany. Чтобы завершить наш пример пользователя / роли, давайте определим метод users в ролевой модели:

Как видите, отношение определяется точно так же, как и его аналог модели User, за исключением ссылки на модель App \ Models \ User. Поскольку мы повторно используем метод ownToMany, все обычные параметры настройки таблиц и ключей доступны при определении "обратный" отношений "многие-ко-многим".

Получение промежуточных столбцов таблицы.

Как вы уже узнали, для работы с отношениями «многие ко многим» требуется наличие промежуточной таблицы. Eloquent предоставляет несколько очень полезных способов взаимодействия с этой таблицей. Например, предположим, что наша модель пользователя имеет много ролевых моделей, с которыми она связана. После доступа к этой связи мы можем получить доступ к промежуточной таблице, используя атрибут pivot в моделях:

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

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

Если вы хотите, чтобы ваша промежуточная таблица имела временные метки created_at и updated_at, которые автоматически поддерживаются Eloquent, вызовите метод withTimestamps при определении отношения:

Промежуточные таблицы, которые используют автоматически поддерживаемые метки времени Eloquent, должны иметь столбцы меток времени created_at и updated_at..

Настройка имени атрибута поворота.

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

Например, если ваше приложение содержит пользователей, которые могут подписаться на подкасты, вы, вероятно, имеете отношение «многие ко многим» между пользователями и подкастами. В этом случае вы можете захотеть переименовать атрибут промежуточной таблицы в subscription вместо pivot. Это можно сделать с помощью метода as при определении отношения:

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

Фильтрация запросов по промежуточным столбцам таблицы.

Вы также можете отфильтровать результаты, возвращаемые запросами отношения принадлежитТоМани, используя методы wherePivot, wherePivotIn и wherePivotNotIn при определении отношения:

Определение пользовательских моделей промежуточных таблиц.

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

Пользовательские модели сводных таблиц «многие ко многим» должны расширять класс Illuminate \ Database \ Eloquent \ Relations \ Pivot, в то время как настраиваемые полиморфные модели сводных диаграмм «многие ко многим» должны расширять класс Illuminate \ Database \ Eloquent \ Relations \ MorphPivot. Например, мы можем определить ролевую модель, которая использует настраиваемую сводную модель RoleUser:

При определении модели RoleUser следует расширить класс Illuminate \ Database \ Eloquent \ Relations \ Pivot:

Сводные модели могут не использовать свойство SoftDeletes. Если вам нужно мягко удалить сводные записи, подумайте о преобразовании вашей сводной модели в реальную модель Eloquent..

Пользовательские модели Pivot и увеличивающиеся идентификаторы.

Если вы определили отношение « многие ко многим », в котором используется настраиваемая сводная модель, и эта сводная модель имеет автоматически увеличивающийся первичный ключ, вы должны убедиться, что ваш класс настраиваемой сводной модели определяет свойство приращения, для которого установлено значение true .

Полиморфные отношения.

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

Один к одному (полиморфный)

Структура таблицы.

Полиморфное отношение «один-к-одному» похоже на типичное взаимно-однозначное отношение; однако дочерняя модель может принадлежать более чем к одному типу моделей с помощью одной ассоциации. Например, сообщение в блоге и пользователь могут иметь полиморфное отношение к модели изображения. Использование однозначного полиморфного отношения позволяет вам иметь единую таблицу уникальных изображений, которые могут быть связаны с сообщениями и пользователями. Сначала рассмотрим структуру таблицы:

Обратите внимание на столбцы imageable_id и imageable_type в таблице изображений. Столбец imageable_id будет содержать значение идентификатора сообщения или пользователя, а столбец imageable_type будет содержать имя класса родительской модели. Столбец imageable_type используется Eloquent для определения того, какой "тип" родительской модели для возврата при доступе к изображаемому отношению. В этом случае столбец будет содержать либо App \ Models \ Post, либо App \ Models \ User. .

Структура модели.

Затем давайте рассмотрим определения модели, необходимые для построения этой связи:

Получение отношения.

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

Вы можете получить родительский элемент полиморфной модели, обратившись к имени метода, который выполняет вызов morphTo. В данном случае это метод изображения в модели Image. Итак, мы будем обращаться к этому методу как к свойству динамического отношения:

Отношение imageable в модели Image будет возвращать экземпляр Post или User, в зависимости от того, какой тип модели владеет изображением..

Основные условные обозначения.

При необходимости вы можете указать название "я бы" и "тип" столбцы, используемые вашей полиморфной дочерней моделью. Если вы это сделаете, убедитесь, что вы всегда передаете имя отношения в качестве первого аргумента метода morphTo. Обычно это значение должно соответствовать имени метода, поэтому вы можете использовать константу PHP __FUNCTION__:

Один ко многим (полиморфный)

Структура таблицы.

Полиморфное отношение «один ко многим» похоже на типичное отношение «один ко многим»; однако дочерняя модель может принадлежать более чем к одному типу моделей с помощью одной ассоциации. Например, представьте, что пользователи вашего приложения могут "комментарий" на постах и ​​видео. Используя полиморфные отношения, вы можете использовать одну таблицу комментариев, чтобы содержать комментарии как к сообщениям, так и к видео. Во-первых, давайте рассмотрим структуру таблицы, необходимую для построения этой связи:

Структура модели.

Затем давайте рассмотрим определения модели, необходимые для построения этой связи:

Получение отношения.

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

Вы также можете получить родительский элемент полиморфной дочерней модели, обратившись к имени метода, который выполняет вызов morphTo. В данном случае это комментируемый метод в модели Comment. Итак, мы будем обращаться к этому методу как к свойству динамического отношения, чтобы получить доступ к родительской модели комментария:

Отношение commentable в модели Comment вернет либо экземпляр Post, либо Video, в зависимости от того, какой тип модели является родительским для комментария..

Многие ко многим (полиморфный)

Структура таблицы.

Полиморфные отношения многие-ко-многим немного сложнее, чем "преобразовать один" и "трансформировать многие" отношения. Например, модель Post и модель видео могут иметь полиморфное отношение к модели тега. Использование полиморфного отношения «многие ко многим» в этой ситуации позволит вашему приложению иметь единую таблицу уникальных тегов, которые могут быть связаны с сообщениями или видео. Во-первых, давайте рассмотрим структуру таблицы, необходимую для построения этой связи:

Прежде чем погрузиться в полиморфные отношения "многие-ко-многим", вам может быть полезно прочитать документацию по типичным отношениям "многие-ко-многим"..

Структура модели.

Далее мы готовы определить отношения на моделях. Модели Post и Video будут содержать метод тегов, который вызывает метод morphToMany, предоставляемый базовым классом модели Eloquent..

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

Определение обратной связи.

Затем в модели Tag вы должны определить метод для каждой из ее возможных родительских моделей. Итак, в этом примере мы определим метод сообщений и метод видео. Оба эти метода должны возвращать результат метода morphedByMany..

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

Получение отношения.

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

Вы можете получить родительский элемент полиморфного отношения из полиморфной дочерней модели, обратившись к имени метода, который выполняет вызов morphedByMany. В данном случае это методы публикации или видео в модели тегов:

Пользовательские полиморфные типы.

По умолчанию Laravel будет использовать полное имя класса для хранения "тип" соответствующей модели. Например, учитывая приведенный выше пример отношения «один ко многим», где модель комментария может принадлежать модели публикации или видео, по умолчанию commentable_type будет либо App \ Models \ Post, либо App \ Models \ Video, соответственно. Однако вы можете захотеть отделить эти значения от внутренней структуры вашего приложения..

Например, вместо использования названий моделей в качестве "тип", мы можем использовать простые строки, такие как сообщение и видео. Таким образом, полиморфный "тип" значения столбцов в нашей базе данных останутся действительными, даже если модели будут переименованы:

Вы можете зарегистрировать morphMap в функции загрузки вашего класса App \ Providers \ AppServiceProvider или создать отдельного поставщика услуг, если хотите..

Вы можете определить морфинговый псевдоним данной модели во время выполнения, используя метод модели getMorphClass. И наоборот, вы можете определить полное имя класса, связанное с псевдонимом морфа, используя метод Relation :: getMorphedModel:

При добавлении "карта морфа" в существующее приложение, каждое значение столбца изменяемого * _type в вашей базе данных, которое все еще содержит полностью определенный класс, необходимо преобразовать в его "карта" имя.

Динамические отношения.

Вы можете использовать метод resolveRelationUsing для определения отношений между моделями Eloquent во время выполнения. Хотя обычно это не рекомендуется для нормальной разработки приложений, иногда это может быть полезно при разработке пакетов Laravel..

Метод resolveRelationUsing принимает желаемое имя отношения в качестве своего первого аргумента. Второй аргумент, передаваемый методу, должен быть замыканием, которое принимает экземпляр модели и возвращает действительное определение отношения Eloquent. Как правило, вы должны настроить динамические отношения в методе загрузки поставщика услуг:

При определении динамических отношений всегда предоставляйте явные аргументы имени ключа методам связи Eloquent..

Запрос отношений.

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

Например, представьте себе приложение для блога, в котором модель User имеет много связанных моделей Post:

Вы можете запросить отношения сообщений и добавить дополнительные ограничения к отношениям, например:

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

Цепочка предложений orWhere после отношений.

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

В приведенном выше примере будет сгенерирован следующий SQL. Как видите, предложение or предписывает запросу возвращать любого пользователя с более чем 100 голосами. Запрос больше не ограничен конкретным пользователем:

В большинстве случаев вам следует использовать логические группы для группирования условных проверок в круглых скобках:

В приведенном выше примере будет получен следующий SQL. Обратите внимание, что логическая группировка правильно сгруппировала ограничения, и запрос остается ограниченным для конкретного пользователя:

Методы взаимоотношений Vs. Динамические свойства.

Если вам не нужно добавлять дополнительные ограничения в запрос отношения Eloquent, вы можете получить доступ к взаимосвязи, как если бы это было свойство. Например, продолжая использовать наши примеры моделей User и Post, мы можем получить доступ ко всем сообщениям пользователя следующим образом:

Свойства динамических отношений работают "ленивая загрузка", Это означает, что они будут загружать данные о своих отношениях только тогда, когда вы действительно обращаетесь к ним. Из-за этого разработчики часто используют активную загрузку для предварительной загрузки отношений, которые, как они знают, будут доступны после загрузки модели. Активная загрузка обеспечивает значительное сокращение количества SQL-запросов, которые необходимо выполнить для загрузки отношений модели..

Запрос существования отношений.

При извлечении записей модели вы можете захотеть ограничить свои результаты в зависимости от наличия связи. Например, представьте, что вы хотите получить все сообщения в блоге, в которых есть хотя бы один комментарий. Для этого вы можете передать имя отношения методам has и orHas:

Вы также можете указать оператор и значение счетчика для дальнейшей настройки запроса:

Вложенные операторы has могут быть построены с использованием "точка" обозначение. Например, вы можете получить все сообщения, в которых есть хотя бы один комментарий с хотя бы одним изображением:

Если вам нужно еще больше возможностей, вы можете использовать методы whereHas и orWhereHas для определения дополнительных ограничений запроса для ваших запросов has, таких как проверка содержимого комментария:

Eloquent в настоящее время не поддерживает запросы о существовании отношений между базами данных. Отношения должны существовать в одной базе данных.

Запрос отсутствия связи.

При извлечении записей модели вы можете захотеть ограничить свои результаты на основании отсутствия связи. Например, представьте, что вы хотите получить все сообщения в блоге, у которых нет комментариев. Для этого вы можете передать имя отношения методам doesntHave и orDoesntHave:

Если вам нужно еще больше возможностей, вы можете использовать методы whereDoesntHave и илиWhereDoesntHave, чтобы добавить дополнительные ограничения запросов к вашим запросам DoesntHave, например, для проверки содержимого комментария:

Вы можете использовать "точка" нотация для выполнения запроса к вложенным отношениям. Например, следующий запрос будет извлекать все сообщения, у которых нет комментариев; однако сообщения с комментариями от авторов, которые не забанены, будут включены в результаты:

Запрос морфа к отношениям.

Чтобы запросить существование "превратиться в" отношений, вы можете использовать методы whereHasMorph и whereDoesntHaveMorph. Эти методы принимают имя отношения в качестве своего первого аргумента. Затем методы принимают имена связанных моделей, которые вы хотите включить в запрос. Наконец, вы можете предоставить закрытие, которое настраивает запрос отношения:

Иногда вам может потребоваться добавить ограничения запроса на основе "тип" соответствующей полиморфной модели. Замыкание, переданное методу whereHasMorph, может получить значение $ type в качестве второго аргумента. Этот аргумент позволяет вам проверить "тип" строящегося запроса:

Запрос всех связанных моделей.

Вместо передачи массива возможных полиморфных моделей вы можете указать * в качестве подстановочного знака. Это проинструктирует Laravel извлечь все возможные полиморфные типы из базы данных. Laravel выполнит дополнительный запрос, чтобы выполнить эту операцию:

Агрегирование связанных моделей.

Подсчет связанных моделей.

Иногда вам может потребоваться подсчитать количество связанных моделей для данного отношения, не загружая их на самом деле. Для этого вы можете использовать метод withCount. Метод withCount, который поместит атрибут _count в результирующие модели:

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

Вы также можете использовать псевдоним результата подсчета отношений, разрешив несколько подсчетов для одной и той же связи:

Загрузка отложенного счета.

Используя метод loadCount, вы можете загрузить счетчик отношений после того, как родительская модель уже была получена:

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

Подсчет отношений & Пользовательские операторы выбора.

Если вы комбинируете withCount с оператором select, убедитесь, что вы вызываете withCount после метода select:

Другие агрегатные функции.

Помимо метода withCount, Eloquent предоставляет методы withMin, withMax, withAvg и withSum. Эти методы добавят атрибут _ _ к вашим результирующим моделям:

Как и метод loadCount, также доступны отложенные версии этих методов. Эти дополнительные агрегатные операции могут выполняться на уже полученных моделях Eloquent:

Подсчет связанных моделей при преобразовании в отношения.

Если вы хотите загрузить "превратиться в" отношения, а также количество связанных моделей для различных сущностей, которые могут быть возвращены этим отношением, вы можете использовать метод with в сочетании с методом morphWithCount отношения morphTo.

В этом примере предположим, что модели Photo и Post могут создавать модели ActivityFeed. Предположим, что модель ActivityFeed определяет "превратиться в" отношение с именем parentable, которое позволяет нам получить родительскую модель Photo или Post для данного экземпляра ActivityFeed. Кроме того, предположим, что фотомодели "есть много" Модели тегов и модели сообщений "есть много" Комментировать модели.

Теперь представим, что мы хотим получить экземпляры ActivityFeed и с нетерпением загрузить родительские родительские модели для каждого экземпляра ActivityFeed. Кроме того, мы хотим получить количество тегов, связанных с каждой родительской фотографией, и количество комментариев, связанных с каждым родительским постом:

Загрузка отложенного счета.

Предположим, мы уже получили набор моделей ActivityFeed, и теперь мы хотели бы загрузить счетчики вложенных отношений для различных родительских моделей, связанных с потоками действий. Для этого вы можете использовать метод loadMorphCount:

Нетерпеливая загрузка.

При доступе к отношениям Eloquent как к свойствам связанные модели "ленивая загрузка". Это означает, что данные отношения фактически не загружаются, пока вы впервые не получите доступ к свойству. Однако Eloquent может "нетерпеливый груз" отношения во время запроса родительской модели. Активная загрузка облегчает "N + 1" проблема с запросом. Чтобы проиллюстрировать проблему запроса N + 1, рассмотрим модель книги, которая "принадлежит" к авторской модели:

Теперь давайте найдем все книги и их авторов:

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

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

Для этой операции будут выполнены только два запроса — один запрос для получения всех книг и один запрос для получения всех авторов для всех книг:

Жажда загрузки множественных отношений.

Иногда вам может потребоваться загрузить несколько разных отношений. Для этого просто передайте массив отношений методу with:

Вложенная нетерпеливая загрузка.

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

Вложенная жадная загрузка отношений morphTo.

Если вы хотите загрузить отношение morphTo, а также вложенные отношения для различных сущностей, которые могут быть возвращены этим отношением, вы можете использовать метод with в сочетании с методом morphWith отношения morphTo. Чтобы проиллюстрировать этот метод, давайте рассмотрим следующую модель:

В этом примере предположим, что модели Event, Photo и Post могут создавать модели ActivityFeed. Кроме того, предположим, что модели событий принадлежат модели календаря, модели фотографий связаны с моделями тегов, а модели сообщений принадлежат модели автора..

Используя эти определения и отношения моделей, мы можем извлекать экземпляры модели ActivityFeed и загружать все родительские модели и их соответствующие вложенные отношения:

Активная загрузка определенных столбцов.

Вам не всегда может понадобиться каждый столбец из извлекаемых вами отношений. По этой причине Eloquent позволяет вам указать, какие столбцы отношения вы хотите получить:

При использовании этой функции вы всегда должны включать столбец идентификатора и любые соответствующие столбцы внешнего ключа в список столбцов, которые вы хотите получить..

Активная загрузка по умолчанию.

Иногда вам может потребоваться всегда загружать некоторые отношения при извлечении модели. Для этого вы можете определить свойство $ with в модели:

Если вы хотите удалить элемент из свойства $ with для одного запроса, вы можете использовать метод without:

Ограничение нетерпеливой нагрузки.

Иногда вам может потребоваться активная загрузка отношения, но также указать дополнительные условия запроса для запроса активной загрузки. Это можно сделать, передав массив отношений в метод with, где ключ массива — это имя отношения, а значение массива — это замыкание, которое добавляет дополнительные ограничения к запросу нетерпеливой загрузки:

В этом примере Eloquent будет загружать только сообщения, в которых столбец заголовка сообщения содержит код слова. Вы можете вызвать другие методы построителя запросов для дальнейшей настройки операции активной загрузки:

Методы конструктора запросов limit и take нельзя использовать при ограничении нетерпеливых нагрузок..

Ограничение нетерпеливой загрузки отношений morphTo.

Если вы хотите загрузить отношение morphTo, Eloquent выполнит несколько запросов для получения каждого типа связанной модели. Вы можете добавить дополнительные ограничения к каждому из этих запросов, используя метод ограничения отношения MorphTo:

В этом примере Eloquent будет загружать только те сообщения, которые не были скрыты, а видео имеют значение типа "образовательный".

Ленивая загрузка.

Иногда вам может потребоваться загрузить отношение после того, как родительская модель уже была получена. Например, это может быть полезно, если вам нужно динамически решать, загружать ли связанные модели:

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

Чтобы загрузить отношение только тогда, когда оно еще не было загружено, используйте метод loadMissing:

Вложенная отложенная загрузка & morphTo.

Если вы хотите загрузить отношение morphTo, а также вложенные отношения для различных сущностей, которые могут быть возвращены этим отношением, вы можете использовать метод loadMorph..

Этот метод принимает имя отношения morphTo в качестве первого аргумента и массив пар модель / отношение в качестве второго аргумента. Чтобы проиллюстрировать этот метод, давайте рассмотрим следующую модель:

В этом примере предположим, что модели Event, Photo и Post могут создавать модели ActivityFeed. Кроме того, предположим, что модели событий принадлежат модели календаря, модели фотографий связаны с моделями тегов, а модели сообщений принадлежат модели автора..

Используя эти определения и отношения моделей, мы можем извлекать экземпляры модели ActivityFeed и загружать все родительские модели и их соответствующие вложенные отношения:

Вставка & Обновление связанных моделей.

Метод сохранения.

Eloquent предоставляет удобные методы для добавления новых моделей в отношения. Например, возможно, вам нужно добавить новый комментарий к сообщению. Вместо того, чтобы вручную устанавливать атрибут post_id в модели комментариев, вы можете вставить комментарий, используя метод сохранения отношения:

Обратите внимание, что мы не обращались к взаимосвязи комментариев как к динамическому свойству. Вместо этого мы вызвали метод комментариев, чтобы получить экземпляр отношения. Метод save автоматически добавит соответствующее значение post_id в новую модель комментариев..

Если вам нужно сохранить несколько связанных моделей, вы можете использовать метод saveMany:

Методы save и saveMany не будут добавлять новые модели ни в какие отношения в памяти, которые уже загружены в родительскую модель. Если вы планируете получить доступ к взаимосвязи после использования методов save или saveMany, вы можете использовать метод обновления для перезагрузки модели и ее взаимосвязей:

Рекурсивное сохранение моделей & Отношения.

Если вы хотите сохранить свою модель и все связанные с ней отношения, вы можете использовать метод push. В этом примере будет сохранена модель Post, а также ее комментарии и авторы комментария:

Метод создания.

В дополнение к методам save и saveMany вы также можете использовать метод create, который принимает массив атрибутов, создает модель и вставляет ее в базу данных. Разница между save и create заключается в том, что save принимает полный экземпляр модели Eloquent, а create принимает простой массив PHP. Вновь созданная модель будет возвращена методом create:

Вы можете использовать метод createMany для создания нескольких связанных моделей:

Вы также можете использовать методы findOrNew, firstOrNew, firstOrCreate и updateOrCreate для создания и обновления моделей отношений..

Перед использованием метода создания обязательно ознакомьтесь с документацией по массовому назначению..

Принадлежит к отношениям.

Если вы хотите назначить дочернюю модель новой родительской модели, вы можете использовать метод associate. В этом примере модель User определяет отношение ownTo к модели Account. Этот ассоциированный метод установит внешний ключ для дочерней модели:

Чтобы удалить родительскую модель из дочерней модели, вы можете использовать метод разобщения. Этот метод установит для внешнего ключа отношения значение null:

Отношения многие ко многим.

Присоединение / отсоединение.

Eloquent также предоставляет методы, которые делают работу с отношениями «многие ко многим» более удобными. Например, представим, что у пользователя может быть много ролей, а у роли может быть много пользователей. Вы можете использовать метод attach, чтобы прикрепить роль к пользователю, вставив запись в промежуточную таблицу отношения:

При присоединении отношения к модели вы также можете передать массив дополнительных данных для вставки в промежуточную таблицу:

Иногда может потребоваться удалить роль пользователя. Чтобы удалить запись отношения «многие ко многим», используйте метод отсоединения. Метод detach удалит соответствующую запись из промежуточной таблицы; однако обе модели останутся в базе данных:

Для удобства команды attach и detach также принимают в качестве входных данных массивы идентификаторов:

Синхронизация ассоциаций.

Вы также можете использовать метод синхронизации для создания ассоциаций "многие ко многим". Метод синхронизации принимает массив идентификаторов для размещения в промежуточной таблице. Любые идентификаторы, которых нет в данном массиве, будут удалены из промежуточной таблицы. Итак, после завершения этой операции в промежуточной таблице будут существовать только идентификаторы из данного массива:

Вы также можете передать дополнительные промежуточные значения таблицы с идентификаторами:

Если вы не хотите отсоединять существующие идентификаторы, которые отсутствуют в данном массиве, вы можете использовать метод syncWithoutDetaching:

Переключение ассоциаций.

Отношение "многие ко многим" также предоставляет метод переключения, который "переключает" статус прикрепления данных идентификаторов связанных моделей. Если данный идентификатор в настоящее время прикреплен, он будет отключен. Аналогичным образом, если он в настоящее время отсоединен, он будет прикреплен:

Обновление записи в промежуточной таблице.

Если вам нужно обновить существующую строку в промежуточной таблице ваших отношений, вы можете использовать метод updateExistingPivot. Этот метод принимает внешний ключ промежуточной записи и массив атрибутов для обновления:

Прикосновение к родительским отметкам времени.

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

Например, при обновлении модели комментариев вы можете захотеть автоматически "трогать" временная метка updated_at записи-владельца, чтобы она была установлена ​​на текущую дату и время. Для этого вы можете добавить в свою дочернюю модель свойство touches, содержащее имена отношений, для которых должны обновляться временные метки updated_at при обновлении дочерней модели:

Временные метки родительской модели будут обновлены только в том случае, если дочерняя модель обновлена ​​с помощью метода сохранения Eloquent..

Похожие статьи