Skip to Content
Course content

129: Laravel Eloquent ORM Relationships

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've sat through countless code reviews where a developer looks at a line like $user->posts()->where('active', 1)->get() and asks why they can't just do $user->posts->where('active', 1). At first glance, they look identical. In fact, if you're just trying to get a list of posts, they often produce the same result. But this reveals a fundamental misunderstanding of how Eloquent handles relationships.

The "Method vs. Property" Confusion

The biggest misconception I see is the belief that $user->posts and $user->posts() are just two different ways of doing the same thing. They aren't. They are entirely different tools.

When you access $user->posts (the property), you are using a Dynamic Property. Laravel executes the query for you, fetches all the related posts from the database, and wraps them in a Collection. Once that happens, you are no longer talking to the database; you are filtering data in PHP's memory.

When you access $user->posts() (the method), you are getting the Relationship Object. This is essentially a Query Builder. It hasn't gone to the database yet. This allows you to chain further constraints onto the SQL query before it's ever executed.

// This fetches EVERY post for the user into memory, then filters with PHP.
// If the user has 10,000 posts, your server might crash.
$activePosts = $user->posts->where('active', 1); 

// This adds "AND active = 1" to the SQL query.
// The database only sends back the records you actually need.
$activePosts = $user->posts()->where('active', 1)->get();

Defining One-to-Many and One-to-One Links

To make the above work, we have to define the relationships in our models. Let's assume we're building a simple blogging platform. A User has one Profile (One-to-One) and many Posts (One-to-Many).

In your User model, you'd define them like this:

public function profile()
{
    return $this->hasOne(Profile::class);
}

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

Crucially, the "inverse" must be defined on the other side. The Post model needs to know who it belongs to using the belongsTo method. I always tell my juniors: if you have a hasMany on one side, you almost certainly need a belongsTo on the other.

// Inside Post.php
public function user()
{
    return $this->belongsTo(User::class);
}

Handling the Complexity of Many-to-Many

Now, things get interesting when we talk about Tags. A Post can have many Tags, and a Tag can belong to many Posts. You can't store this in a single column in either table. You need a "pivot table"—usually named alphabetically, like post_tag.

You don't need a Model for the pivot table itself (unless you're doing something very advanced). You just tell Eloquent to use belongsToMany on both ends.

// Inside Post.php
public function tags()
{
    return $this->belongsToMany(Tag::class);
}

// Inside Tag.php
public function posts()
{
    return $this->belongsToMany(Post::class);
}

The beauty of this is that Laravel handles the heavy lifting of joining the three tables behind the scenes. When you call $post->tags, Laravel queries the pivot table to find the IDs and then fetches the actual tags. Just remember: if you're adding a tag to a post, you don't manually insert into the pivot table. You use the attach() method: $post->tags()->attach($tagId);.




📋 Practical Task

Build a Course-Lesson Relationship System

You are tasked with implementing the data layer for a learning management system. You have three existing models: Course, Lesson, and Instructor. Your goal is to establish the correct Eloquent relationships to allow for complex querying.

Requirements:

  • Course & Lesson: A Course has many Lessons. A Lesson belongs to one Course.
  • Course & Instructor: A Course can be co-taught by multiple Instructors, and an Instructor can teach multiple Courses. (Implement this as a Many-to-Many relationship).

Your Task:

  1. Write the relationship methods in the Course, Lesson, and Instructor models.
  2. Write a code snippet that retrieves a specific Course by ID and then uses the relationship method (not the dynamic property) to count how many lessons in that course are marked as 'completed' = true.
  3. Write a line of code that attaches an Instructor with ID 5 to a Course with ID 10.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.