Как получаются результаты с несколькими запросами в Eloquent - PullRequest
0 голосов
/ 25 июня 2019

Отсюда: https://laravel -news.com / eloquent-eager-loading

Запуск этой строки: App\Post::with('author.profile')->get(); приводит к выполнению 3 запросов:

[2017-08-04 07:27:27] local.INFO: select * from `posts`  
[2017-08-04 07:27:27] local.INFO: select * from `authors` where `authors`.`id` in (?, ?, ?, ?, ?) [1,2,3,4,5] 
[2017-08-04 07:27:27] local.INFO: select * from `profiles` where `profiles`.`author_id` in (?, ?, ?, ?, ?) [1,2,3,4,5] 

Как получилось?Есть ли чистый способ сделать это в одном запросе?

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

SELECT * 
FROM posts, authors, profiles 
WHERE posts.author_id = author.id
AND author.profile_id = profiles.id

Ответы [ 2 ]

3 голосов
/ 26 июня 2019

Eloquent выполняет такие запросы, поэтому может гидрировать отдельную модель для каждой строки данных. Это важно для включения других функций Eloquent после загрузки моделей. При энергичной загрузке количество запросов всегда предсказуемо. App\Post::with('author.profile')->get(); всегда будет выполнять три запроса, независимо от количества сообщений, авторов или профилей. Без активной загрузки он будет выполнять экспоненциально больше запросов в зависимости от количества возвращаемых записей. Это результат того, что Eloquent внедрил шаблон проектирования Active Record .

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

Это больше вопрос об использовании Active Record, и он менее специфичен для самого Eloquent. Есть много аргументов за и против использования активной записи, в которые я не буду вдаваться. Для получения дополнительной информации, я бы порекомендовал вам почитать Active Record (используется Eloquent), Data Mapper (используется Doctrine) или, в более общем смысле, шаблоны проектирования ORM.

2 голосов
/ 26 июня 2019

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

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

Примерно так:

\DB::table('posts as p')
    ->join('authors as a', 'p.author_id', '=', 'a.id')
    ->join('profiles as pr', 'pr.id', '=', 'a.profile_id')
    ->get();
...