Hướng dẫn tạo comment trong bài viết cho Laravel

Hướng dẫn tạo comment trong bài viết cho Laravel

Hệ thống bình luận là một phần không thể thiếu đối với trang web blog hoặc bất kỳ trang web hướng dẫn nào. Trong bài viết này tôi muốn chia sẻ với các bạn cách tạo hệ thống bình luận trong ứng dụng laravel.

Hầu hết các nhà phát triển đang tìm kiếm gói tốt cho hệ thống bình luận, nhưng nếu bạn đang sử dụng laravel 5 thì bạn có thể làm hệ thống bình luận lồng nhau bằng cách sử dụng mối quan hệ cơ sở dữ liệu.

Chúng ta sẽ tạo ra hệ thống bình luận rất đơn giản với bạn có thể thêm bình luận và trả lời bình luận. Bạn cũng có thể cải thiện bằng cách thêm bình luận, chỉnh sửa bình luận, xóa bình luận và trả lời bình luận bằng ajax nếu bạn muốn.

Sau khi làm theo hướng dẫn này, bạn không cần sử dụng bất kỳ plugin bình luận nào như disqus, v.v. trong trang web của bạn.

Bước 1: Cài đặt Laravel

Để cài đặt Laravel với môi trường Localhost các bạn có thể tham khảo bài viết sau: Bài 1: Hướng dẫn cài đặt Laravel

Để cài đặt Laravel trên VPS các bạn có thể dùng composer:

composer create-project --prefer-dist laravel/laravel project-name

Bước 2: Cấu hình kết nối database

Để kết nối database các bạn cần chỉnh sửa trong file .env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=here your database name
DB_USERNAME=here database username
DB_PASSWORD=here database password

Bước 3: Tạo Post và Comment Table

Để tạo bảng Post Comment trong database các bạn chạy lệnh sau để tạo migration:

php artisan make:migration create_posts_comments_table

Sau lệnh này, bạn sẽ tìm thấy một tệp trong đường dẫn database/migrations, bạn cần thay thế toàn bộ nội dung file mới tạo bằng nội dung dưới đây:

<?php
  
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
  
class CreatePostsCommentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
            $table->softDeletes();
        });
   
        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();
        });
    }
   
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
        Schema::dropIfExists('comments');
    }
}

Tiếp theo chúng ta chạy lệnh sau:

php artisan migrate

Bước 4: Tạo Auth

Trong bước này, chúng ta cần tạo auth (Xác thực người dùng) bằng cách sử dụng lệnh auth. Laravel cung cấp xác thực người dùng mặc định. vì vậy chỉ cần chạy lệnh dưới đây:

php artisan make:auth

Bước 5: Tạo Post Model

Trong bước này, chúng ta cần tạo Model Post và Comment.  Chạy lệnh dưới đây để tạo model Post:

php artisan make:model Post

Một file Post.php sẽ được tạo ra trong thư mục app.Các bạn sửa lại nội dung file theo dưới đây:

<?php
  
namespace App;
  
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
  
class Post extends Model
{
    use SoftDeletes;
  
    protected $dates = ['deleted_at'];
  
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['title', 'body'];
   
    /**
     * The has Many Relationship
     *
     * @var array
     */
    public function comments()
    {
        return $this->hasMany(Comment::class)->whereNull('parent_id');
    }
}

Bước 6: Tạo Comment Model

Tương tự ở trên các bạn run lệnh sau để tạo Comment Model

php artisan make:model Comment

Nội dung file như sau:

<?php
  
namespace App;
  
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
  
class Comment extends Model
{
    use SoftDeletes;
   
    protected $dates = ['deleted_at'];
   
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['user_id', 'post_id', 'parent_id', 'body'];
   
    /**
     * The belongs to Relationship
     *
     * @var array
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
   
    /**
     * The has Many Relationship
     *
     * @var array
     */
    public function replies()
    {
        return $this->hasMany(Comment::class, 'parent_id');
    }
}

Bước 7: Tạo Controller

Trong bước này chúng ta sẽ tạo PostController CommentController. Chạy lệnh dưới đây để tạo Controller:

a. PostController

php artisan make:controller PostController

app/Http/Controllers/PostController.php

<?php
   
namespace App\Http\Controllers;
   
use Illuminate\Http\Request;
use App\Post;
   
class PostController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $posts = Post::all();
    
        return view('posts.index', compact('posts'));
    }
   
    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('posts.create');
    }
    
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
    	$request->validate([
            'title'=>'required',
            'body'=>'required',
        ]);
    
        Post::create($request->all());
    
        return redirect()->route('posts.index');
    }
    
    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
    	$post = Post::find($id);
        return view('posts.show', compact('post'));
    }
}

b. CommentController

php artisan make:controller CommentController

app/Http/Controllers/CommentController.php

<?php
   
namespace App\Http\Controllers;
   
use Illuminate\Http\Request;
use App\Comment;
   
class CommentController extends Controller
{
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
    	$request->validate([
            'body'=>'required',
        ]);
   
        $input = $request->all();
        $input['user_id'] = auth()->user()->id;
    
        Comment::create($input);
   
        return back();
    }
}

Bước 8: Tạo Blade View

Ở bước cuối cùng chúng ta tạo các file View dưới đây:

a. resources/views/posts/index.blade.php

@extends('layouts.app')
   
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12">
            <h1>Manage Posts</h1>
            <a href="{{ route('posts.create') }}" class="btn btn-success" style="float: right">Create Post</a>
            <table class="table table-bordered">
                <thead>
                    <th width=80px>Id</th>
                    <th>Title</th>
                    <th width=150px>Action</th>
                </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

b. resources/views/posts/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">ItSolutionStuff.com</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

c. resources/views/posts/create.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-header">Create Post</div>
                <div class="card-body">
                    <form method="post" action="{{ route('posts.store') }}">
                        <div class="form-group">
                            @csrf
                            <label class="label">Post Title: </label>
                            <input type=text name=title class="form-control" required/>
                        </div>
                        <div class="form-group">
                            <label class="label">Post Body: </label>
                            <textarea name=body rows="10" cols="30" class="form-control" required></textarea>
                        </div>
                        <div class="form-group">
                            <input type=submit class="btn btn-success" />
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

d.resources/views/posts/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>
        <a href="" id="reply"></a>
        <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

Bây giờ chúng ta truy cập website để test xem thành quả nhé

Post Comment