PHP Profi

Жадная загрузка в Laravel: load() или with()? Перевод

Прим. пер.: Это небольшая заметка о работе методов ::with() и ::load() Laravel Eloquent-а, которую должен знать каждый разработчик, пишущий на Laravel. Тут ничего нового, но, как оказывается, не все об этом знают.

Сегодня, работая с одним из моих проектов (который написан на фреймворке laravel) я столкнулся с ситуацией, когда мне нужно для одной из моделей получить данные по другим моделям, связанные с этой. Так вот, для этого у меня есть два варианта, предоставляемых Laravel-ом, которые обычно называют жадной загрузкой:

Оба метода достигают тех же конечных результатов — жадной загрузки моделей в первую. На самом деле, они оба запускают одни и те же два запроса. Какой выбрать?

Ключевым отличием является то, что with() всегда загружает модели сразу после начального запроса (all(), first() или find(x), например); при использовании load(), выполнится сначала первоначальный запрос, а потом в какой-то момент в будущем выполнится запрос с жадной загрузкой связанных моделей.

“Жадная” здесь означает, что мы прицепляем все связанные модели, используя только один запрос, вместо того, чтобы выполнить 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[$i]->comments[$j]->body.

“Ленивая” жадная загрузка через load()

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

$users = User::all();

который запустит:

select * from `users`

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

if ($someCondition) {
    $users = $users->load('comments');
}

что выполнит второй запрос:

select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)

Это приведёт к такому же результату, просто разделённому на два этапа. Далее, мы всё так же можем сделать $users[$i]->comments[$j]->body чтобы получить соответствующие комментарии для каждого пользователя.

Заключение

Когда использовать load(), а когда with()?

Метод load() дает вам возможность решить позже, основываясь на некоторых динамических условиях, нужно ли вам выполнять второй запрос.

Однако, если нет никаких сомнений, что вам потребуются все связанные элементы, используйте with().

2017-10-23 оригинал

Последние посты

Комментарии

авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий