Advertisement

Google Ad Slot: content-top

One To Many & Many To One


What is One To Many?

  • Definition: One record in a table can have multiple related records in another table.
  • Example:
  • One Post → can have many Comments.
  • (A blog post can receive many comments from users.)
Post → Comments

What is Many To One?

  • Definition: The reverse of One To Many.
  • Example:
  • Many Comments → belong to One Post.
  • (Each comment is always related to one specific post.)
Comments → Post 

Flow diagram


Migration:

Use this command to generate a migration for creating a tables:

php artisan make:migration create_onetomany_manytoone_tables


Migration File

public function up(): void
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->timestamps();
    });

    Schema::create('comments', function (Blueprint $table) {
        $table->id();
        $table->foreignId('post_id')->constrained()->onDelete('cascade');
        $table->string('body');
        $table->timestamps();
    });
}

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


Run Migration

php artisan migrate

Tables

posts table
id title created_at updated_at
comments table
id post_id body created_at updated_at

post_id is the foreign key connecting Comments → Posts.


Model:

Generate a model with Artisan:

php artisan make:model Post
php artisan make:model Comment

This generates 2 files Post.php and Comment.php


Post.php

namespace App\Models;

use App\Models\Comment;
use Illuminate\Database\Eloquent\Model;

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

    // One Post has Many Comments
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}



Comment.php

namespace App\Models;

use App\Models\Post;
use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    protected $fillable = ['post_id', 'body'];

    // Each Comment belongs to One Post
    public function post()
    {
        return $this->belongsTo(Post::class);
    }
}

CRUD Examples

Create

use App\Models\Post;

// Create a Post
$post = Post::create(['title' => 'My Post']);

// Add Comments to that Post
$post->comments()->create(['body' => 'Nice']);
$post->comments()->create(['body' => 'Cool']);
$post->comments()->create(['body' => 'Good']);


// Method 2 Using Eloquent instance
$post2= new Post();
$post2->title= "My Second Post";
$post2->save();

// Add Comments to that Post
$post2->comments()->create(['body' => 'This is Greate']);
$post2->comments()->create(['body' => 'Thank you.']);
Output:
posts table
id title created_at updated_at
1 My Post 2025-08-17 20:38:58 2025-08-17 20:38:58
2 My Second Post 2025-08-17 20:38:58 2025-08-17 20:38:58
comments table
id post_id body created_at updated_at
1 1 Nice 2025-08-17 20:38:58 2025-08-17 20:38:58
2 1 Cool 2025-08-17 20:38:58 2025-08-17 20:38:58
3 1 Good 2025-08-17 20:38:58 2025-08-17 20:38:58
4 2 This is Greate 2025-08-17 20:38:58 2025-08-17 20:38:58
5 2 Thank you. 2025-08-17 20:38:58 2025-08-17 20:38:58

👉 Here, post_id is automatically set in the comments.


Read

use App\Models\Post;
use App\Models\Comment;

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

// Get the post for a specific comment
$comment = Comment::find(1);
echo $comment->post->title; // "My Post"

Update

use App\Models\Post;
use App\Models\Comment;

// Update a comment
$comment = Comment::find(1);
$comment->body = "Updated comment text";
$comment->save();

// Update post and its comments
$post = Post::find(1);
$post->title = "Updated Post Title";
$post->save();

Delete

use App\Models\Post;
use App\Models\Comment;

// Delete a single comment
Comment::find(1)->delete();

// Delete a post → all its comments will also be deleted (cascade)
Post::find(2)->delete();

Eager loading (optimizes queries)

use App\Models\Post;
use App\Models\Comment;

// Get all comments for a post
$post = Post::with('comments')->find(1);
foreach ($post->comments as $comment) {
  echo $comment->body;
}

// Get the post for a specific comment
$comment = Comment::with('post')->find(1);
echo $comment->post->title; // "My First Post"

Always use with() when fetching related data in bulk.