Почему Laravel/Eloquent не может использовать JOIN для Eager Loading?
<?php
class Cat extends Eloquent {
public function user() {
return $this->belongsTo('User');
}
}
class User extends Eloquent {
public function cats() {
return $this->hasMany('Cat');
}
}
Сейчас:
$cats = Cat::with('user')->get();
Выполняет 2 запроса:
select * from `cats`
select * from `users` where `users`.`id` in ('1', '2', 'x')
Почему он не может этого сделать:
select * from cats inner join users on cats.user_id = users.id
Для тех, кто говорит, что в таблице есть оба столбца id, которые можно легко избежать с помощью псевдонимов:
select
c.id as cats__id,
c.name as cats__name,
c.user_id as cats__user_id,
b.id as users__id,
b.name as users__name
from cats c
inner join users b on b.id = c.user_id
ОБНОВЛЕНИЕ
Кто-то указал, что Eloquent не знает столбцов таблиц из моделей, но я предполагаю, что они могли бы предоставить способ определить их в модели, чтобы затем использовать псевдонимы и делать правильное соединение вместо дополнительного запрос.
Ответы
Ответ 1
Моя догадка заключается в том, что это позволяет загружать несколько отношений друг к другу. Скажем, например, у нас также был стол для собак:
class User extends Eloquent {
public function cats() {
return $this->hasMany('Cat');
}
public function dogs() {
return $this->hasMany('Dog');
}
}
Теперь мы хотим, чтобы они загружали их как с помощью пользователя:
$users = User::with('cats','dogs')->get();
Нет объединения, которое могло бы объединить их в один запрос. Однако выполнение отдельного запроса для каждого элемента "с" действительно работает:
select * from `users`
select * from `cats` where `user`.`id` in ('1', '2', 'x')
select * from `dogs` where `user`.`id` in ('1', '2', 'x')
Таким образом, хотя эта методология может привести к дополнительному запросу в некоторых простых обстоятельствах, она обеспечивает возможность загружать более сложные данные, когда метод объединения будет терпеть неудачу.
Это мое предположение, почему это так.
Ответ 2
cats
и users
вероятно, оба имеют столбец с именем id
, оставляя ваш предложенный запрос неоднозначным. При загрузке Laravel требуется дополнительный запрос, но он избегает этого потенциального сбоя.