Laravel 11 Comment Reply System Tutorial

Using this Laravel 11 Comment Reply System Tutorial you will learn how to build a comment and reply system in a Laravel application. In a Laravel 11 application, setting up a comment and reply system is straightforward with Eloquent relationships. Let’s see the step by step guide:

Step 1 – Create Post and Comment Migration Files

Execute these commands to generate migration files for posts and comments, along with their models:

php artisan make:model Post -m
php artisan make:model Comment -m

Modify the database/migrations/posts.php file to include:

Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->timestamps();
$table->softDeletes();
});

Update the database/migrations/comments.php file with:

Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('post_id')->unsigned();
$table->integer('parent_id')->unsigned()->nullable();
$table->text('body');
$table->timestamps();
$table->softDeletes();
});

Step 2 – Define Relationships Between Tables

Edit the app/Models/Post.php file to set up the relationship with comments:

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
use SoftDeletes;

protected $dates = ['deleted_at'];
protected $fillable = ['title', 'body'];

public function comments()
{
return $this->hasMany(Comment::class)->whereNull('parent_id');
}
}

Update the app/Models/Comment.php file to define its relationships with users and other comments:

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Comment extends Model
{
use SoftDeletes;

protected $dates = ['deleted_at'];
protected $fillable = ['user_id', 'post_id', 'parent_id', 'body'];

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

public function replies()
{
return $this->hasMany(Comment::class, 'parent_id');
}
}

Step 3 – Set Up Bootstrap Authentication

Install Laravel UI for authentication scaffolding:

composer require laravel/ui

Generate the authentication system using Bootstrap:

php artisan ui bootstrap --auth

Compile the Bootstrap assets:

npm install
npm run dev

Step 4 – Create Controllers

Generate a controller for posts:

php artisan make:controller PostController

Edit the app/Http/Controllers/PostController.php file to include:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Post;

class PostController extends Controller
{
public function index()
{
$posts = Post::all();
return view('posts.index', compact('posts'));
}

public function show($id)
{
$post = Post::find($id);
return view('posts.show', compact('post'));
}
}

Generate a controller for comments:

php artisan make:controller CommentController

Edit the app/Http/Controllers/CommentController.php file to add:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Comment;

class CommentController extends Controller
{
public function store(Request $request)
{
$request->validate([
'body' => 'required',
]);

$input = $request->all();
$input['user_id'] = auth()->user()->id;

Comment::create($input);

return back();
}
}

Step 5 – Define Routes

Update the routes/web.php file to include:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
use App\Http\Controllers\CommentController;

Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
Route::get('/posts/{id}', [PostController::class, 'show'])->name('posts.show');
Route::post('/comments', [CommentController::class, 'store'])->name('comments.store');

Step 6 – Create Views

In the resources/views directory, create views to display posts, comment forms, and comments.

Create index.blade.php:

@extends('layouts.app')

@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12">
<h1>Post List</h1>
<a href="{{ route('posts.create') }}" class="btn btn-success" style="float: right">Create Post</a>
<table class="table table-bordered">
<thead>
<tr>
<th width="80px">Id</th>
<th>Title</th>
<th width="150px">Action</th>
</tr>
</thead>
<tbody>
@foreach($posts as $post)
<tr>
<td>{{ $post->id }}</td>
<td>{{ $post->title }}</td>
<td>
<a href="{{ route('posts.show', $post->id) }}" class="btn btn-primary">View Post</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endsection

Create show.blade.php:

@extends('layouts.app')

@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-body">
<h3 class="text-center text-success">Details</h3>
<br/>
<h2>{{ $post->title }}</h2>
<p>{{ $post->body }}</p>
<hr />
<h4>Display Comments</h4>

@include('posts.commentsDisplay', ['comments' => $post->comments, 'post_id' => $post->id])

<hr />
<h4>Add comment</h4>
<form method="post" action="{{ route('comments.store') }}">
@csrf
<div class="form-group">
<textarea class="form-control" name="body"></textarea>
<input type="hidden" name="post_id" value="{{ $post->id }}" />
</div>
<div class="form-group">
<input type="submit" class="btn btn-success" value="Add Comment" />
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection

Create commentsDisplay.blade.php:

@foreach($comments as $comment)
    <div class="display-comment" @if($comment->parent_id != null) style="margin-left:40px;" @endif>
        <strong>{{ $comment->user->name }}</strong>
        <p>{{ $comment->body }}</p>
        <form method="post" action="{{ route('comments.store') }}">
            @csrf
            <div class="form-group">
                <input type="text" name="body" class="form-control" />
                <input type="hidden" name="post_id" value="{{ $post_id }}" />
                <input type="hidden" name="parent_id" value="{{ $comment->id }}" />
            </div>
            <div class="form-group">
                <input type="submit" class="btn btn-warning" value="Reply" />
            </div>
        </form>
        @include('posts.commentsDisplay', ['comments' => $comment->replies])
    </div>
@endforeach

Step 7 – Test Your Application

Start the Laravel development server:

php artisan serve

Visit http://localhost:8000/posts in your browser to test the application.