Laravel Eloquent relationships have a bunch of "with" methods you might not know about.

Laravel Eloquent relationships have a bunch of "with" methods you might not know about.
Photo by Joshua Earle / Unsplash

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 to 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 a model. Let's say you have a User and Post model and want to include the number of posts per user when making a query. You would normally have set up your User model with a posts() method like this:

public function posts(): HasMany
{
    return $this->hasMany(Post::class);
}
User.php

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 the number of posts per user are included in the resulting model instance. You'd be able to get to the posts count like this:

$posts = $users->first()->posts_count;

But did you know that there are a few more than just withCount?

withMax and withMin

withMax and 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 the posts can 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 doing something like this:

$max = User::withMax('posts as max_rating', 'rating')->get();

withSum

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 User instance.

withAvg

The 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 withAvg method:

$contacts = ContactList::orderBy('title')
    ->withAvg('contacts as rating', 'rating')
    ->get();

This gave us a rating attribute on every ContactList model instance. We didn't need to do any math in the application. The database did the heavy lifting for us and we got the results we needed.

Subscribe to THEPUBLICGOOD Blog

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe