We are going to add the possibility for logged users to comment on posts.
First, we have to add the comments table in the database. For that, as always, we have to create a migration:
1 |
php artisan make:migration create_comments_table |
With this code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateCommentsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('comments', function (Blueprint $table) { $table->increments('id'); $table->text('body'); $table->integer('user_id')->references('id')->on('users')->onDelete('cascade'); $table->integer('post_id')->references('id')->on('posts')->onDelete('cascade'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('comments'); } } |
And execute it.
Once we have this, we have to create the controller and the model for the comments. Laravel allows us to do this simply with one command:
1 |
php artisan make:controller CommentsController --model=Comment |
Open the Comment.php model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; use App\Presenters\DatePresenter; class Comment extends Model { use DatePresenter; // fields can be filled protected $fillable = ['body', 'user_id', 'post_id']; public function post() { return $this->belongsTo('App\Post'); } public function user() { return $this->belongsTo('App\User'); } } |
Add the relationships with comments in the Post.php and User.php models:
1 2 3 4 |
public function comments() { return $this->hasMany('App\Comment'); } |
1 2 3 4 |
public function comments() { return $this->hasMany('App\Comment'); } |
When you have this, we can access the comments of a posts and a user’s comments easily.
Open the controller and add the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php namespace App\Http\Controllers; use App\Comment; use App\Post; use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; use App\Http\Requests\CommentRequest; class CommentsController extends Controller { public function __construct() { $this->middleware('auth'); } public function store(CommentRequest $request) { $post = Post::findOrFail($request->post_id); Comment::create([ 'body' => $request->body, 'user_id' => Auth::id(), 'post_id' => $post->id ]); return redirect()->route('posts.show', $post->id); } } |
We only add the store method, which is the one that creates the comment in the database, later we will add more functionalities.
Before continuing, we must modify the route that shows the detail of a post and add a name:
1 |
Route::get('/post/{id}', 'PostsController@show')->name('posts.show'); |
Now, we create the Form Request to validate the information sent of the comment we want to insert ( php artisan make:request CommentRequest) and add this code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class CommentRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return \Auth::check(); } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'body' => 'required|max:1000', ]; } } |
Check that the user is logged in and that the comment has content and that it is maximum 1000 characters.
Add the route:
1 |
Route::resource('comments', 'CommentsController'); |
If you look, we have added the route another way. This way adds all routes automatically, without having to add one by one.
We add the form and the list of comments of a post to the view:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<h3>Comments</h3> @if (Auth::check()) @include('includes.errors') {{ Form::open(['route' => ['comments.store'], 'method' => 'POST']) }} <p>{{ Form::textarea('body', old('body')) }}</p> {{ Form::hidden('post_id', $post->id) }} <p>{{ Form::submit('Send') }}</p> {{ Form::close() }} @endif @forelse ($post->comments as $comment) <p>{{ $comment->user->name }} {{$comment->created_at}}</p> <p>{{ $comment->body }}</p> <hr> @empty <p>This post has no comments</p> @endforelse |
And if we want, we can add the number of comments that one post have in the list of posts:
1 |
<span>{{$post->comments->count()}} {{ str_plural('comment', $post->comments->count()) }}</span> |
str_plural function will help us to transform a string to plural according to the number we pass.