Laravel Eloquent relationships have a bunch of “with” methods you might not know about.
Eloquent is the database ORM that is included with Laravel. Taylor Otwell recently stated that it’s one of the most complex pieces of Laravel to maintain. Yet it’s probably one of the most important reasons why Laravel has become so super popular.
You may already have a good handle of how Eloquent works and there’s a bunch of useful tools that are included. One those tools you might already know about is the
withCount method. This is really handy if you need to include a count of a related model. Let’s say you have a
Post model and want to include the number of posts per user when making a query. You would probably have your
User model set up with a
posts() method like this:
public function posts(): HasMany
Your Eloquent query would then look something like this:
$users = User::withCount('posts')->get();
Eloquent will automatically build up the queries for you so that you get the number of posts per user included in the resulting model instance, which you can get to like this:
$posts = $users->first()->posts_count;
But did you know that there are a few more than just
withMax and withMin
withMin methods can be used to get the maximum or minimum value of an attribute on the related model. Using the example from above, let's say posts have a rating. You might want to know what the highest, or the lowest rating is across all the users posts.
// Get the highest rating
$max = User::withMax('posts', 'rating')->get();
// Or the lowest rating
$min = User::withMin('posts', 'rating')->get();
Eloquent will include a
posts_max_rating or a
posts_min_rating on the
User model instance. You can even rename the attribute if you want by using the “as” syntax like this:
$max = User::withMax(‘posts as max_rating’, ‘rating’)->get();
Similarly, you can use the
withSum method to get the total value of all the ratings added together.
$total = User::withSum('posts as total_rating', 'rating')->get();
You’d get a
posts_sum_rating attribute on each
withAvg method is really handy if you need to know what the average rating is across multiple relations. For a recent project we needed to know what the rating was of a list of contacts. Each contact was giving a health rating out of 100 and we wanted to give the list a rating as well based on the health of each contact. We can get the average rating across all the contacts on the list in one query using the
$contacts = ContactList::orderBy('title')
->withAvg('contacts as rating', 'rating')
This gives us a
rating attribute on every
ContactList model instance. We didn’t need to do any math in our code. The database did the heavy lifting for us and we got the results we needed.