Я нашел концепцию и значение этих методов немного запутанными, возможно ли, чтобы кто-то объяснил мне, в чем разница между has
и with
в контексте примера (если это возможно)?
Я нашел концепцию и значение этих методов немного запутанными, возможно ли, чтобы кто-то объяснил мне, в чем разница между has
и with
в контексте примера (если это возможно)?
Ответы:
with()
для нетерпеливой загрузки . Это в основном означает, что вдоль основной модели Laravel будет предварительно загружать указанные вами отношения. Это особенно полезно, если у вас есть коллекция моделей, и вы хотите загрузить отношение для всех них. Потому что при активной загрузке вы запускаете только один дополнительный запрос БД вместо одного для каждой модели в коллекции.
Пример:
User > hasMany > Post
$users = User::with('posts')->get();
foreach($users as $user){
$users->posts; // posts is already loaded and no additional DB query is run
}
has()
является фильтрация модели выбора на основе отношений. Так что он действует очень похоже на нормальное состояние ГДЕ. Если вы просто используете это, has('relation')
это означает, что вы хотите получить только модели, имеющие хотя бы одну связанную модель в этом отношении.
Пример:
User > hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
whereHas()
работает в основном так же, как, has()
но позволяет вам указать дополнительные фильтры для связанной модели для проверки.
Пример:
User > hasMany > Post
$users = User::whereHas('posts', function($q){
$q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned
whereHas
отношение пользователя при запросе поста.
whereHas
он использует use Illuminate\Database\Eloquent\Builder;
то, что с function(Builder $query)
. Большинство примеров, которые я видел, используют точку Builder
, просто передают запрос $, что является правильным способом?
Документ уже объяснил использование. Поэтому я использую SQL для объяснения этих методов
Предполагая, что Order (orders)
есть много OrderItem (order_items)
.
И вы уже выстроили отношения между ними.
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
Эти три метода основаны на отношениях .
Результат: with()
вернуть объект модели и связанные с ним результаты.
Преимущество: это энергичная загрузка, которая может предотвратить проблему N + 1 .
Когда вы используете следующий Eloquent Builder:
Order::with('orderItems')->get();
Laravel изменить этот код только на два SQL :
// get all orders:
SELECT * FROM orders;
// get the order_items based on the orders' id above
SELECT * FROM order_items WHERE order_items.order_id IN (1,2,3,4...);
И затем laravel объединить результаты второго SQL как отличные от результатов первого SQL путем внешнему ключу . Наконец верните результаты сбора.
Таким образом, если вы выбрали столбцы без Foreign_key в закрытии, результат отношения будет пустым:
Order::with(['orderItems' => function($query) {
// $query->sum('quantity');
$query->select('quantity'); // without `order_id`
}
])->get();
#=> result:
[{ id: 1,
code: '00001',
orderItems: [], // <== is empty
},{
id: 2,
code: '00002',
orderItems: [], // <== is empty
}...
}]
Has
вернет объект модели, что ее отношение не пустое .
Order::has('orderItems')->get();
Laravel измените этот код на один SQL :
select * from `orders` where exists (
select * from `order_items` where `order`.`id` = `order_item`.`order_id`
)
whereHas
и orWhereHas
методы наложения where
условий на ваши has
запросы. Эти методы позволяют добавлять настраиваемые ограничения в ограничение отношений .
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel измените этот код на один SQL :
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
with('relation')
будет включать данные связанной таблицы в возвращенную коллекциюhas('relation')
и неwhereHas('relation')
будет включать данные связанной таблицы. Таким образом, вам может понадобиться позвонить как, так и или .with('relation')
has()
whereHas()