SyntaxStudy
Sign Up
Laravel Eloquent Relationships: hasMany, belongsTo, belongsToMany
Laravel Beginner 1 min read

Eloquent Relationships: hasMany, belongsTo, belongsToMany

Eloquent relationships are defined as methods on model classes and return relationship objects that act as query builders. The three most common relationships are hasMany (one-to-many), belongsTo (inverse one-to-many), and belongsToMany (many-to-many). A User hasMany Posts means one user can have multiple posts. A Post belongsTo a User means each post references a single user. The foreign key conventions are applied automatically but can be overridden. Many-to-many relationships require a pivot table. By default, Laravel expects the table name to be the two model names in alphabetical order, joined by an underscore (post_tag). The pivot table holds the foreign keys of both related models. Additional columns on the pivot table are declared with withPivot() and accessed via the $relation->pivot property on the related model. Eager loading with the with() method solves the N+1 query problem by loading relationships in a minimal number of queries. Lazy eager loading with load() can be used after the fact. The withCount() method adds a {relation}_count attribute without loading the related records. Deep eager loading uses dot notation: with('user.profile') loads the user and their profile in a single query chain.
Example
<?php
// Defining relationships in models

// app/Models/User.php
class User extends Model
{
    // One user has many posts
    public function posts()
    {
        return $this->hasMany(Post::class);
    }

    // One user has one profile
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
}

// app/Models/Post.php
class Post extends Model
{
    // Each post belongs to a user
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    // Post belongs to many tags (pivot: post_tag)
    public function tags()
    {
        return $this->belongsToMany(Tag::class)
            ->withPivot('order')
            ->withTimestamps();
    }
}

// Usage in a controller:
// Eager load to avoid N+1
$posts = Post::with(['user', 'tags'])->published()->paginate(10);

// Attach/sync many-to-many
$post->tags()->sync([1, 2, 3]);

// Access pivot data
foreach ($post->tags as $tag) {
    echo $tag->pivot->order;
}