Blog Detail

31

Dec
Some Awesome Tips & Tricks about Laravel Models Relations cover image

arrow_back Some Awesome Tips & Tricks about Laravel Models Relations

Laravel 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. Laravel relationships can be kind of hard to wrap your head around. If you don’t fully understand how relationships in Laravel work at this point. Don’t worry, In this blog, I’ve collected some useful tips and tricks about the laravel model relationships that can assist you to upgrade your Laravel web development process.

New whereBelongsTo() Eloquent query builder method

Laravel 8.63.0 ships with a new whereBelongsTo() Eloquent query builder method. This allows you to remove BelongsTo foreign key names from your queries, and use the relationship method as a single source of truth instead!

// From:
$query->where('author_id', $author->id)

// To:
$query->whereBelongsTo($author)

// Easily add more advanced filtering:
Post::query()
    ->whereBelongsTo($author)
    ->whereBelongsTo($cateogry)
    ->whereBelongsTo($section)
    ->get();

// Specify a custom relationship:
$query->whereBelongsTo($author, 'author')

The is() method of one-to-one relationships for comparing models

We can now make comparisons between related models without further database access.

// BEFORE: the foreign key is taken from the Post model
$post->author_id === $user->id;

// BEFORE: An additional request is made to get the User model from the Author relationship
$post->author->is($user);

// AFTER
$post->author()->is($user);

Use hasMany to create Many

If you have hasMany() relationship, you can use saveMany() to save multiple “child” entries from your “parent” object, all in one sentence.

$post = Post::find(1);
$post->comments()->saveMany([
    new Comment(['message' => 'First comment']),
    new Comment(['message' => 'Second comment']),
]);

Multi-level Eager Loading

In Laravel you can Eager Load multiple levels in one statement, in this example, we not only load the author relation but also the country relation on the author model.

$users = App\Book::with('author.country')->get();

Eager Loading with Exact Columns

You can do Laravel Eager Loading and specify the exact columns you want to get from the relationship.

$users = App\Book::with('author:id,name')->get();

You can do that even in deeper, second level relationships:

$users = App\Book::with('author.country:id,name')->get();

Extra Filter Query on Relationships

If you want to load relationship data, you can specify some limitations or orders in a closure function. For example, if you want to get Countries with only three of their biggest cities, here’s the code.

$countries = Country::with(['cities' => function($query) {
    $query->orderBy('population', 'desc');
    $query->take(3);
}])->get();

Instead of belongsTo, use hasMany

For belongsTo relationship, instead of passing parent’s ID when creating child record, use hasMany relationship to make a shorter sentence.

// if Post -> belongsTo(User), and User -> hasMany(Post)...
// Then instead of passing user_id...
Post::create([
    'user_id' => auth()->id(),
    'title' => request()->input('title'),
    'post_text' => request()->input('post_text'),
]);

// Do this
auth()->user()->posts()->create([
    'title' => request()->input('title'),
    'post_text' => request()->input('post_text'),
]);

Combine Two “whereHas”

In Eloquent, you can combine whereHas()and orDoesntHave() in one sentence.

User::whereHas('roles', function($query) {
    $query->where('id', 1);
})
->orDoesntHave('roles')
->get();

Check if Relationship Method Exists

If your Eloquent relationship names are dynamic and you need to check if the relationship with such name exists on the object, use PHP function method_exists($object, $methodName).

$user = User::first();
if (method_exists($user, 'roles')) {
	// Do something with $user->roles()->...
}

A shorter way to write whereHas

Released in Laravel 8.57: a shorter way to write whereHas() with a simple condition inside.

// Before
User::whereHas('posts', function ($query) {
    $query->where('published_at', '>', now());
})->get();

// After
User::whereRelation('posts', 'published_at', '>', now())->get();

You can add conditions to your relationships

class User
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
    
    // with a getter
    public function getPublishedPostsAttribute()
    {
        return $this->posts->filter(fn ($post) => $post->published);
    }
    
    // with a relationship
    public function publishedPosts()
    {
        return $this->hasMany(Post::class)->where('published', true);
    }
}

Note

I hope that by following these tips & tricks you can improve your code quality & performance and improve your coding journey. If you are a business and want to leverage Laravel for your next PHP-based web application development for your custom requirements, you must discover an exquisite team with proficiency in the Laravel framework. So Codebrisk is here to help you with your tailored requirements regarding Laravel Development.

Have an awesome idea? Please feel free to send us an email at rizwan@codebrisk.com or get in touch with us, our business person will get back to you.

Published at : 31-12-2021

Author : Rizwan Aslam
AUTHOR
Rizwan Aslam

I am a highly results-driven professional with 12+ years of collective experience in the grounds of web application development especially in laravel, native android application development in java, and desktop application development in the dot net framework. Now managing a team of expert developers at Codebrisk.

Launch your project

Launch project