Laravel Advanced: Little Known Relationships - hasOneThrough() and hasManyThrough()

You've probably used hasOne, hasMany, belongsTo, and belongsToMany relationships in your projects. But did you know Laravel also offers...

Karan Datwani
Karan Datwani
Share:

You've probably used hasOne, hasMany, belongsTo, and belongsToMany relationships in your projects. But did you know Laravel also offers hasOneThrough and hasManyThrough relationships? They’re perfect for accessing nested relationships without extra hassle. Let's break it down.

Imagine you have a project management app with the following tables:

  1. Users: Represents users in the system.
  2. Projects: Each user can have multiple projects.
  3. Tasks: Each project can have multiple tasks.
  4. Statuses: Each task has a status (e.g. pending, completed).

Setting Up Models & Relationships

Let's define our models and their relationships in our Laravel project.

🟡 Project Model

class Project extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function tasks()
    {
        return $this->hasMany(Task::class);
    }
}

🟡 Task Model

class Task extends Model
{
    public function project()
    {
        return $this->belongsTo(Project::class);
    }
    public function status()
    {
        return $this->hasOne(Status::class);
    }
}

🟡 Status Model

class Status extends Model
{
    public function task()
    {
        return $this->belongsTo(Task::class);
    }
}

🔴 User Model

class User extends Model
{
    public function projects()
    {
        return $this->hasMany(Project::class);
    }

    public function tasks()
    {
        return $this->hasManyThrough(Task::class, Project::class);
    }

    public function status()
    {
        return $this->hasOneThrough(Status::class, Task::class);
    }
}

Using hasManyThrough

In the User model, we used hasManyThrough to get all tasks for a user, even though tasks are directly related to projects. Here’s how you can use it:

$user = User::find(1);
$tasks = $user->tasks;

foreach ($tasks as $task) {
    echo $task->name;
}

Using hasOneThrough

You can access the status of a task directly from a user:

$user = User::find(1);
$status = $user->status;

echo $status->name;

It fetches the status of the first task it encounters (based on the database query order).

Wrapping Up

The hasOneThrough and hasManyThrough relationships can simplify your code to easily access deeply nested relationships. They’re perfect for scenarios where you need to traverse multiple levels of relationships.

Give them a try in your next Laravel project and see how they can clean up your code and make your life easier.

All the above have been previously shared on our Twitter, one by one. Follow us on Twitter - you'll ❤️ it. You can also check the first article of the series, which is on the Top 5 Scheduler Functions you might not know about. Keep exploring, and keep coding with ease using Laravel. Until next time, happy coding! 🚀

Want to receive more articles like this?

Subscribe to our "Article Digest". We'll send you a list of the new articles, every week, month or quarter - your choice.

Reactions & Comments

What do you think about this?

Latest Articles

Wondering what our community has been up to?