Ответ 1
Оба выполняют одни и те же конечные результаты - стремятся загрузить связанную модель на первую. Фактически, они оба выполняют точно такие же два запроса. Главное отличие заключается в том, что with()
нетерпеливо загружает связанную модель вперед, сразу после первоначального запроса (all()
, first()
или find(x)
, например); при использовании load()
вы сначала запускаете начальный запрос, а затем загружаете отношение в некоторой более поздней точке.
"Eager" означает, что мы связываем все связанные модели для определенного набора результатов, используя только один запрос, в отличие от необходимости запуска запросов n, где n - количество элементов в исходном наборе.
Загрузка с использованием with()
Если мы хотим загрузить с помощью with()
, например:
$users = User::with('comments')->get();
... если у нас есть 5 пользователей, следующие два запроса запускаются немедленно:
select * from `users`
select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)
... и мы получаем набор моделей, которые имеют комментарии к пользовательской модели, поэтому мы можем сделать что-то вроде $users->comments->first()->body
.
"ленивая" загрузка с использованием load()
Или мы можем отделить два запроса, сначала получив исходный результат:
$users = User::all();
который запускается:
select * from `users`
И позже, если мы решим, что нам нужны соответствующие комментарии для всех этих пользователей, мы можем их загрузить после факта:
$users = $users->load('comments');
который запускает второй запрос:
select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)
... и мы получим тот же результат, просто разделим на два шага. Опять же, мы можем вызвать $users->comments->first()->body
, чтобы перейти к соответствующей модели для любого элемента.
Зачем использовать load()
vs. with()
? load()
дает вам возможность позже решить, основываясь на каком-либо динамическом состоянии, нужно ли вам выполнить второй запрос. Если, однако, нет вопроса, что вам нужно получить доступ ко всем связанным элементам, используйте with()
. (Документы также ссылаются на преимущества кэширования для использования load(), но я не знаком с этим, на самом деле, я считаю, что результаты load()
не кэшируемы.)
Альтернативой любому из этих элементов будет цикл через исходный набор результатов и запрос отношения hasMany()
для каждого элемента. В этом примере это приведет к выполнению запросов n + 1 или 6. Желаемая загрузка, независимо от того, была ли она выполнена с помощью with()
или более поздней версии с load()
, выполняется только 2.