with() function is used to eager load in Laravel. Unless of using 2 or more separate queries to fetch data from the database , we can use it with() method after the first command. It provides a better user experience as we do not have to wait for a longer period of time in fetching data from the database.
Eloquent relationships are defined as methods on your Eloquent model classes. Since relationships also serve as powerful query builders, defining relationships as methods provides powerful method chaining and querying capabilities.
hasOne relationship in laravel is used to create the relation between two tables. hasOne means create the relation one to one. For example if a article has comments and we wanted to get one comment with the article details then we can use hasOne relationship or a user can have a profile table.
with()
is for eager loading. That basically means, along the main model, Laravel will preload the relationship(s) you specify. This is especially helpful if you have a collection of models and you want to load a relation for all of them. Because with eager loading you run only one additional DB query instead of one for every model in the collection.
Example:
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()
is to filter the selecting model based on a relationship. So it acts very similarly to a normal WHERE condition. If you just use has('relation')
that means you only want to get the models that have at least one related model in this relation.
Example:
User > hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
whereHas()
works basically the same as has()
but allows you to specify additional filters for the related model to check.
Example:
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
The documentation has already explained the usage, so I will use SQL to explain the methods.
Assuming there is an Order (orders)
has many OrderItem (order_items)
and you already built the relationship between them:
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
These three methods are all based on a relationship.
Result: with()
return the model object and its related results.
Advantage: It is eager-loading which can prevent the N+1 problem.
When you are using the following Eloquent Builder:
Order::with('orderItems')->get();
Laravel change this code to only two 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...);
And then Laravel merges the results of the second SQL query with the results of the first SQL by foreign key, finally returning the collection results.
So if you selected columns without the foreign_key in a closure, the relationship result will be empty:
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
will return the model's object when its relationship is not empty.
Order::has('orderItems')->get();
Laravel changes this code to one SQL query:
select * from `orders` where exists (
select * from `order_items` where `orders`.`id` = `order_items`.`order_id`
)
The methods whereHas
and orWhereHas
put where
conditions on your has
queries. These methods allow you to add customized constraints to a relationship constraint.
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel changes this code to one SQL query:
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With