Laravel Eloquent Relationships: Best Practices and Examples to Optimize Your Database Queries

Laravel Eloquent Relationships: Best Practices and Examples to Optimize Your Database Queries

Laravel is a powerful PHP framework that makes it easy to build modern web applications. One of its most robust features is Eloquent ORM, which allows developers to work with database records using an object-oriented approach.

In this blog post, we will dive deep into Laravel relationships, explaining their types, usage, and best practices.

What Are Laravel Relationships?

In Laravel, relationships define how database tables are linked together. Instead of writing complex SQL queries, Laravel allows developers to define relationships in models and use simple methods to retrieve related data.

Types of Relationships in Laravel

Laravel provides several types of relationships to accommodate different database structures. Let's explore each type with examples.

1. One-to-One Relationship

What is a One-to-One Relationship?

A one-to-one relationship means that a single record in one table is associated with a single record in another table.

Example Scenario:

  • Each User has exactly one Profile.
  • Each Profile belongs to only one User.

Step 1: Create Migration Files

We need two tables:

  1. users (already available by default in Laravel).
  2. profiles (we will create this table).

Create a Profile Table

Run the following command to generate the migration:

php artisan make:migration create_profiles_table --create=profiles

Now, open the generated migration file inside database/migrations/xxxx_xx_xx_create_profiles_table.php and define the table structure:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('profiles', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->onDelete('cascade'); // Foreign key
            $table->string('bio')->nullable();
            $table->string('avatar')->nullable();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('profiles');
    }
};

Explanation:

  • id(): Primary key of the profiles table.
  • user_id: Foreign key that references the users table.
  • constrained(): Ensures that user_id must exist in the users table.
  • onDelete('cascade'): If a user is deleted, their profile will also be deleted.

Now, run the migration:

php artisan migrate

Step 2: Define the Relationship in Models

We need to define the one-to-one relationship in both User and Profile models.

User Model (app/Models/User.php)

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;

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

Profile Model (app/Models/Profile.php)

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Profile extends Model
{
    protected $fillable = ['user_id', 'bio', 'avatar'];

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

Explanation:

  • hasOne(Profile::class) in User model: This means a user has one profile.
  • belongsTo(User::class) in Profile model: This means a profile belongs to a user.

Step 3: Insert Data into the Database

1. Creating a User and Profile

$user = User::create([
    'name' => 'John Doe',
    'email' => 'johndoe@example.com',
    'password' => bcrypt('password123')
]);

$profile = new Profile([
    'bio' => 'Web Developer',
    'avatar' => 'john-avatar.png'
]);

$user->profile()->save($profile);

Alternative: Using create() method

$user->profile()->create([
    'bio' => 'Web Developer',
    'avatar' => 'john-avatar.png'
]);

Explanation:

  • $user->profile()->save($profile): Associates the profile with the user.
  • $user->profile()->create([...]): Creates and associates the profile in one step.

Step 4: Fetching Data

1. Get a User’s Profile

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

echo "User: " . $user->name;
echo "Bio: " . $profile->bio;

2. Get a Profile’s User

$profile = Profile::find(1);
$user = $profile->user;

echo "User: " . $user->name;
echo "Profile Bio: " . $profile->bio;

Step 5: Eager Loading (Performance Optimization)

By default, Laravel loads relationships lazily, meaning it queries them when needed. However, this can lead to N+1 query issues.

Solution: Use Eager Loading

To load a user with their profile in a single query:

$users = User::with('profile')->get();
foreach ($users as $user) {
    echo $user->profile->bio;
}

This reduces the number of queries and improves performance.

Step 6: Updating and Deleting Related Data

1. Updating a User’s Profile

$user = User::find(1);
$user->profile()->update(['bio' => 'Updated Bio']);

2. Deleting a Profile

$user->profile()->delete();

3. Deleting a User (Cascading Delete)

Since we set onDelete('cascade') in the migration, deleting a user will also delete their profile:

User::find(1)->delete();

Step 7: Factory & Seeder (Optional)

If you are using factories for testing, you can define factories like this:

User Factory (database/factories/UserFactory.php)

use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\User;

class UserFactory extends Factory
{
    protected $model = User::class;

    public function definition(): array
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'password' => bcrypt('password'),
        ];
    }
}

Profile Factory (database/factories/ProfileFactory.php)

use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Profile;

class ProfileFactory extends Factory
{
    protected $model = Profile::class;

    public function definition(): array
    {
        return [
            'user_id' => User::factory(),
            'bio' => $this->faker->sentence,
            'avatar' => 'default.png',
        ];
    }
}

Seeding Data (database/seeders/DatabaseSeeder.php)

User::factory()->count(10)->has(Profile::factory())->create();

Summary of One-to-One Relationship in Laravel (User & Profile Example)

  • Create Migration: Add user_id as a foreign key in the profiles table with onDelete('cascade').
  • Define Relationship in Models:
    • User model: hasOne(Profile::class).
    • Profile model: belongsTo(User::class).
  • Insert Data:
    • $user->profile()->create([...]); (Quick method).
    • $user->profile()->save($profile); (Manual method).
  • Retrieve Data:
    • $user->profile; (Get profile from user).
    • $profile->user; (Get user from profile).
  • Optimize Performance: Use eager loading with User::with('profile')->get();.
  • Update Profile Data: $user->profile()->update([...]);.
  • Delete Profile: $user->profile()->delete();.
  • Delete User & Profile (Cascade Delete): $user->delete();.
  • Use Factories for Testing: User::factory()->has(Profile::factory())->create();.

Final Thoughts

  • This is a typical one-to-one relationship setup in Laravel.
  • It follows Laravel’s Eloquent ORM best practices.
  • Cascading delete ensures data integrity.
  • Eager loading prevents performance issues.


2. One-to-Many Relationship

One-to-Many Relationship in Laravel (User & Posts Example)

Definition:

A one-to-many relationship means that a single record in one table is related to multiple records in another table.

Example:

  • A User can have many Posts.
  • Each Post belongs to only one User.

Steps to Implement in Laravel

1. Create Migration for posts Table

php artisan make:migration create_posts_table --create=posts

Edit the migration file (database/migrations/xxxx_xx_xx_create_posts_table.php):

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->onDelete('cascade'); // Foreign key
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

Run the migration:

php artisan migrate

2. Define Relationship in Models

User Model (app/Models/User.php):

use Illuminate\Database\Eloquent\Relations\HasMany;

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

Post Model (app/Models/Post.php):

use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Post extends Model
{
    protected $fillable = ['user_id', 'title', 'content'];

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

3. Insert Data into the Database

$user = User::create([
    'name' => 'John Doe',
    'email' => 'johndoe@example.com',
    'password' => bcrypt('password123')
]);

// Create posts for the user
$user->posts()->create([
    'title' => 'First Post',
    'content' => 'This is the first post content.'
]);

$user->posts()->create([
    'title' => 'Second Post',
    'content' => 'This is another post content.'
]);

4. Retrieve Data

  • Get all posts of a user:
  • $user = User::find(1);
    foreach ($user->posts as $post) {
        echo $post->title;
    }
    
  • Get the user who created a post:
  • $post = Post::find(1);
    echo $post->user->name;
    

5. Optimize Performance with Eager Loading

$users = User::with('posts')->get();
foreach ($users as $user) {
    echo $user->name . ' has ' . $user->posts->count() . ' posts.';
}

6. Updating & Deleting Related Data

  • Update a post:
  • $user->posts()->where('id', 1)->update(['title' => 'Updated Title']);
    
  • Delete a post:
  • $user->posts()->where('id', 1)->delete();
    
  • Delete a user & their posts (cascade delete):
  • $user->delete(); // Will delete posts automatically due to `onDelete('cascade')`
    

7. Using Factories for Testing

Post Factory (database/factories/PostFactory.php):

use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    protected $model = Post::class;

    public function definition(): array
    {
        return [
            'user_id' => User::factory(),
            'title' => $this->faker->sentence,
            'content' => $this->faker->paragraph,
        ];
    }
}

Seeding Data (database/seeders/DatabaseSeeder.php):

User::factory()->count(5)->hasPosts(3)->create();

Summary

  • Create posts table with a foreign key to users.
  • Define Relationships:
    • User → hasMany(Post::class).
    • Post → belongsTo(User::class).
  • Insert Data: Use $user->posts()->create([...]).
  • Retrieve Data:
    • $user->posts (Get posts from user).
    • $post->user (Get user from post).
  • Optimize Queries: Use eager loading User::with('posts')->get();.
  • Update & Delete: Cascade delete ensures related posts are removed when a user is deleted.
  • Testing: Use factories for bulk data generation.

3. Many-to-Many Relationship

Many-to-Many Relationship in Laravel (Users & Roles Example)

Definition:

A many-to-many relationship occurs when multiple records in one table are related to multiple records in another table.

Example:

  • A User can have multiple Roles (e.g., Admin, Editor).
  • A Role can belong to multiple Users.
  • A pivot table (role_user) is needed to manage the relationship.

Steps to Implement in Laravel

1. Create Migrations for Users, Roles & Pivot Table

php artisan make:migration create_roles_table --create=roles
php artisan make:migration create_role_user_table --create=role_user

Edit roles migration (database/migrations/xxxx_xx_xx_create_roles_table.php):

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->id();
            $table->string('name')->unique();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('roles');
    }
};

Edit role_user pivot table migration (database/migrations/xxxx_xx_xx_create_role_user_table.php):

return new class extends Migration {
    public function up(): void
    {
        Schema::create('role_user', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->onDelete('cascade');
            $table->foreignId('role_id')->constrained()->onDelete('cascade');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('role_user');
    }
};

Run the migrations:

php artisan migrate

2. Define Relationship in Models

User Model (app/Models/User.php):

use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class User extends Model
{
    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(Role::class);
    }
}

Role Model (app/Models/Role.php):

use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Role extends Model
{
    public function users(): BelongsToMany
    {
        return $this->belongsToMany(User::class);
    }
}

3. Insert Data into the Database

$user = User::create([
    'name' => 'John Doe',
    'email' => 'johndoe@example.com',
    'password' => bcrypt('password123')
]);

$adminRole = Role::create(['name' => 'Admin']);
$editorRole = Role::create(['name' => 'Editor']);

// Assign roles to user
$user->roles()->attach([$adminRole->id, $editorRole->id]);

4. Retrieve Data

  • Get all roles for a user:
  • $user = User::find(1);
    foreach ($user->roles as $role) {
        echo $role->name;
    }
    
  • Get all users with a specific role:
  • $role = Role::where('name', 'Admin')->first();
    foreach ($role->users as $user) {
        echo $user->name;
    }
    

5. Attach, Detach & Sync Roles

  • Attach new roles:
  • $user->roles()->attach($roleId);
    
  • Detach a specific role:
  • $user->roles()->detach($roleId);
    
  • Detach all roles:
  • $user->roles()->detach();
    
  • Sync roles (remove old & add new ones):
  • $user->roles()->sync([$adminRole->id, $editorRole->id]); 
    
  • Toggle roles (attach if missing, detach if exists):
  • $user->roles()->toggle([$adminRole->id, $editorRole->id]);
    

6. Optimize Queries with Eager Loading

$users = User::with('roles')->get();
foreach ($users as $user) {
    echo $user->name . ' has roles: ' . implode(', ', $user->roles->pluck('name')->toArray());
}

7. Using Factories for Testing

Role Factory (database/factories/RoleFactory.php):

use Illuminate\Database\Eloquent\Factories\Factory;

class RoleFactory extends Factory
{
    protected $model = Role::class;

    public function definition(): array
    {
        return [
            'name' => $this->faker->unique()->word,
        ];
    }
}

Seeding Data (database/seeders/DatabaseSeeder.php):

User::factory()->count(5)->hasAttached(Role::factory()->count(2))->create();

Summary

  • Pivot Table: role_user stores user_id and role_id.
  • Define Relationships:
    • User → belongsToMany(Role::class).
    • Role → belongsToMany(User::class).
  • Insert Data: $user->roles()->attach([$roleId1, $roleId2]);.
  • Retrieve Data:
    • $user->roles (Get roles for user).
    • $role->users (Get users for role).
  • Modify Relationships:
    • attach(), detach(), sync(), toggle().
  • Optimize Queries: Use eager loading User::with('roles')->get();.
  • Testing: Use factories and seeders for bulk data generation.

4. Has-One-Through Relationship

A has-one-through relationship allows you to access a related model that is connected through an intermediate model.

Example: Country → User → Post

class Country extends Model
{
    public function post()
    {
        return $this->hasOneThrough(Post::class, User::class);
    }
}

Usage:

$country = Country::find(1);
$post = $country->post;

5. Has-Many-Through Relationship

Has-Many-Through Relationship in Laravel (Example: Country → Users → Posts)

Definition:

A has-many-through relationship allows accessing distant related models through an intermediate model.

Example:

  • A Country has many Users.
  • A User has many Posts.
  • A Country has many Posts through Users.

Steps to Implement in Laravel

1. Create Migrations for Countries, Users, and Posts

php artisan make:migration create_countries_table --create=countries
php artisan make:migration create_users_table --create=users
php artisan make:migration create_posts_table --create=posts

Edit countries migration (database/migrations/xxxx_xx_xx_create_countries_table.php):

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('countries', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('countries');
    }
};

Edit users migration (database/migrations/xxxx_xx_xx_create_users_table.php):

return new class extends Migration {
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->foreignId('country_id')->constrained()->onDelete('cascade'); // Foreign key to countries
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

Edit posts migration (database/migrations/xxxx_xx_xx_create_posts_table.php):

return new class extends Migration {
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->foreignId('user_id')->constrained()->onDelete('cascade'); // Foreign key to users
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

Run the migrations:

php artisan migrate

2. Define Relationships in Models

Country Model (app/Models/Country.php):

use Illuminate\Database\Eloquent\Relations\HasManyThrough;

class Country extends Model
{
    public function posts(): HasManyThrough
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}

  • This tells Laravel that a Country can access Posts through Users.

User Model (app/Models/User.php):

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class User extends Model
{
    public function country(): BelongsTo
    {
        return $this->belongsTo(Country::class);
    }

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

Post Model (app/Models/Post.php):

use Illuminate\Database\Eloquent\Relations\BelongsTo;

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

3. Insert Data into the Database

$country = Country::create(['name' => 'USA']);

$user1 = User::create(['name' => 'John Doe', 'country_id' => $country->id]);
$user2 = User::create(['name' => 'Jane Smith', 'country_id' => $country->id]);

Post::create(['title' => 'Laravel Tips', 'user_id' => $user1->id]);
Post::create(['title' => 'PHP Best Practices', 'user_id' => $user2->id]);

4. Retrieve Data

  • Get all posts for a country:
  • $country = Country::find(1);
    foreach ($country->posts as $post) {
        echo $post->title;
    }
    
    • This fetches all posts via the users of the country.

5. Optimize Queries with Eager Loading

$countries = Country::with('posts')->get();
foreach ($countries as $country) {
    echo "Posts from {$country->name}: " . implode(', ', $country->posts->pluck('title')->toArray());
}

  • Without Eager Loading: Multiple queries per country (N+1 problem).
  • With Eager Loading: Only one query for countries and one for posts.

Summary

  • HasManyThrough is used for indirect relationships (Country → Users → Posts).
  • Setup:
    • countries → users → posts with foreign keys.
    • Country model: hasManyThrough(Post::class, User::class).
  • Retrieve Data: $country->posts fetches all posts through users.
  • Optimize Queries: Use eager loading with Country::with('posts')->get().

6. Polymorphic Relationships

Definition:

A polymorphic relationship allows a model to belong to multiple other models using a single association.

Example:

  • A Post and a Video can both have Comments.
  • Instead of creating separate comment tables for each model, we use one comments table with a polymorphic relationship.

Steps to Implement Polymorphic Relationships in Laravel

1. Create Migrations

Run the following commands:

php artisan make:migration create_posts_table --create=posts
php artisan make:migration create_videos_table --create=videos
php artisan make:migration create_comments_table --create=comments

Edit posts migration (database/migrations/xxxx_xx_xx_create_posts_table.php):

return new class extends Migration {
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

Edit videos migration (database/migrations/xxxx_xx_xx_create_videos_table.php):

return new class extends Migration {
    public function up(): void
    {
        Schema::create('videos', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('url');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('videos');
    }
};

Edit comments migration (database/migrations/xxxx_xx_xx_create_comments_table.php):

return new class extends Migration {
    public function up(): void
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->text('body');
            $table->morphs('commentable'); // Adds `commentable_id` and `commentable_type`
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('comments');
    }
};

Run the migrations:

php artisan migrate

2. Define Relationships in Models

Post Model (app/Models/Post.php)

use Illuminate\Database\Eloquent\Relations\MorphMany;

class Post extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Video Model (app/Models/Video.php)

use Illuminate\Database\Eloquent\Relations\MorphMany;

class Video extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Comment Model (app/Models/Comment.php)

use Illuminate\Database\Eloquent\Relations\MorphTo;

class Comment extends Model
{
    public function commentable(): MorphTo
    {
        return $this->morphTo();
    }
}

3. Insert Data

$post = Post::create(['title' => 'Laravel Tips', 'content' => 'Learn polymorphic relationships.']);
$video = Video::create(['title' => 'Laravel Tutorial', 'url' => 'https://example.com/video']);

$post->comments()->create(['body' => 'Great article!']);
$video->comments()->create(['body' => 'Nice tutorial!']);

4. Retrieve Data

Get Comments for a Post

$post = Post::find(1);
foreach ($post->comments as $comment) {
    echo $comment->body;
}

Get Comments for a Video

$video = Video::find(1);
foreach ($video->comments as $comment) {
    echo $comment->body;
}

Get Parent Model of a Comment

$comment = Comment::find(1);
$parent = $comment->commentable; // Returns either a Post or Video
echo get_class($parent); // App\Models\Post or App\Models\Video

5. Optimize Queries with Eager Loading

$posts = Post::with('comments')->get();
$videos = Video::with('comments')->get();

Summary

  • Polymorphic Relationships allow a single model (Comment) to belong to multiple models (Post, Video).
  • Setup:
    • posts and videos tables.
    • comments table with commentable_id and commentable_type.
  • Retrieve Data: $post->comments, $video->comments.
  • Optimize Queries: Use eager loading with Post::with('comments')->get().

Best Practices for Laravel Relationships

1. Use the Right Relationship Type

  • One-to-One: hasOne(), belongsTo()
  • One-to-Many: hasMany(), belongsTo()
  • Many-to-Many: belongsToMany() with a pivot table
  • Has-Many-Through: hasManyThrough() for indirect relations
  • Polymorphic: morphMany(), morphTo() for flexible relationships

2. Always Define Inverse Relationships

  • If User has a Profile, define both sides: 
  • class User extends Model {
        public function profile() {
            return $this->hasOne(Profile::class);
        }
    }
    class Profile extends Model {
        public function user() {
            return $this->belongsTo(User::class);
        }
    }
    

3. Use Eager Loading to Avoid N+1 Query Problem

  • Instead of running multiple queries: 
  • $users = User::all();  
    foreach ($users as $user) {  
        echo $user->profile->name; // Causes multiple queries  
    }
    
  • Use eager loading to fetch related data in a single query: 
  • $users = User::with('profile')->get();
    

4. Use Foreign Keys & Constraints in Migrations

  • Define foreign keys for data integrity: 
  • Schema::create('profiles', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained()->onDelete('cascade');
    });
    
  • onDelete('cascade') ensures related records are deleted automatically.

5. Use belongsToMany() with a Pivot Table for Many-to-Many

  • Define the relationship with proper pivot table naming: 
  • class User extends Model {
        public function roles() {
            return $this->belongsToMany(Role::class);
        }
    }
    class Role extends Model {
        public function users() {
            return $this->belongsToMany(User::class);
        }
    }
    
  • Pivot table should be named alphabetically (e.g., role_user).

6. Use withPivot() for Extra Fields in Many-to-Many Relationships

  • If a pivot table has additional fields like assigned_at: 
  • class User extends Model {
        public function roles() {
            return $this->belongsToMany(Role::class)->withPivot('assigned_at');
        }
    }
    

7. Use touches() to Auto-Update Timestamps

  • If Post needs to update User's updated_at when modified: 
  • class Post extends Model {
        protected $touches = ['user'];
    }
    

8. Use Model Factories & Seeders for Testing Relationships

  • Create test data easily with factories: 
  • User::factory()->has(Profile::factory())->create();
    

9. Use morphMany() & morphTo() for Polymorphic Relations

  • Example: A Comment can belong to a Post or Video: 
  • class Comment extends Model {
        public function commentable() {
            return $this->morphTo();
        }
    }
    

10. Use Events & Observers for Automatic Relationship Handling

  • Example: When a User is deleted, delete related Profile: 
  • class UserObserver {
        public function deleting(User $user) {
            $user->profile()->delete();
        }
    }
    

Conclusion

Choose the right relationship type
Always define inverse relationships
Use eager loading to prevent N+1 problems
Define foreign keys & constraints
Use pivot tables & withPivot() in many-to-many relations
Leverage model factories for testing relationships
Use morphTo() for polymorphic relationships
Utilize events & observers for automated handling

Start leveraging Laravel relationships today and simplify your database queries!

Happy Coding 


Read More

Efficiently Import Large Excel Files in Laravel and Display Data Using Bootstrap

How to Handle Large Data Exports in Laravel Using Laravel Excel

Mastering Laravel Jobs and Queues: A Comprehensive Guide

Top 50 Laravel Interview Questions and Answers to Crack Your Developer Interview

Building a Blog with Laravel Filament: CRUD, Image Upload, and Slugs

0 Comments