Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

CedricBongaerts's avatar

CommentsController (How to link both user/post to your comment)

I'm making an application where users can both post/comment if they're logged in. Everything works up to the point where I want to post my comment.

This is how my comment table looks like:

        Schema::create('comments', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')->references('id')->on('users')->onCascade('update')->onDelete('cascade');
            $table->integer('post_id')->unsigned();
            $table->foreign('post_id')->references('id')->on('users')->onCascade('update')->onDelete('cascade');
            $table->text('comment');
            $table->timestamps();
            $table->rememberToken();
        });

I've made a post form that triggers the comments.store function in the CommentsController.

This is the view that shows the post/comment area:

@extends('masterpage.app')

@section('content')
        <h1>{{ $post->title }}</h1>
        <h4>{!! nl2br($post->content) !!}</h4>
        @if($post->youtube != '')
            <iframe width="420" height="315" src="http://www.youtube.com/embed/{{$post->youtube}}" frameborder="0" allowfullscreen></iframe>
        @endif

            <div class="panel panel-default">
                    <div class="panel-body">
                        {!! Form::open(['route' => 'comment.store']) !!}

                            <div class="form-group">
                                {!! Form::Textarea('comment', 'Comment here...', ['class' => 'form-control comments']) !!}
                            </div>

                            <div class="form-group">
                                    {!! Form::submit('Leave a comment', ['class' =>  'btn btn-primary']) !!}
                            </div> 
                        {!! Form::close() !!}
                </div>
            </div>

@stop

Now my question is, what do I write in the CommentsController@store to link both my user and the post (where the comment section is under) to that specific post just placed?

Thanks

0 likes
26 replies
ersinkandemir's avatar

store method may accept a postID as a parameter and change the form to use route with parameter: route => ['comments.store', $post->id].

public function store(Request $request, $postID){

    $post = App\Post::findOrFail($postID);
    
    $commentData = array_merge($request->all(), ['user_id' => $request->user()->id]);

    $comment = App\Comment::make($commentData);
    
    $post->comments()->save($comment);

    // return a response
}
CedricBongaerts's avatar

@ersinkandemir when trying this I get this error: ErrorException in CommentsController.php line 22: Missing argument 2 for App\Http\Controllers\CommentsController::store()

CedricBongaerts's avatar

@ersinkandemir Yes I currently have this:

CommentsController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Auth;
use App\User;
use App\Post;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class CommentsController extends Controller
{
    
    /**
     * Adds a comment to a specific post
     */
    public function store(Request $request, $postID){

        $post = App\Post::findOrFail($postID);

        $commentData = array_merge($request->all(), ['user_id' => $request->user()->id]);

        $comment = App\Comment::make($commentData);

        $post->comments()->save($comment);

        return redirect()->back();
    }
}

routes.php

# Comments
    $router->post('', ['as' => 'comment.store', 'uses' => 'CommentsController@store']);

show.blade.php

@extends('masterpage.app')

@section('content')
        <h1>{{ $post->title }}</h1>
        <h4>{!! nl2br($post->content) !!}</h4>
        @if($post->youtube != '')
            <iframe width="420" height="315" src="http://www.youtube.com/embed/{{$post->youtube}}" frameborder="0" allowfullscreen></iframe>
        @endif

            <div class="panel panel-default">
                    <div class="panel-body">
                        {!! Form::open(['route' => 'comment.store', '$postID']) !!}

                            <div class="form-group">
                                {!! Form::Textarea('comment', 'Comment here...', ['class' => 'form-control comments']) !!}
                            </div>

                            <div class="form-group">
                                    {!! Form::submit('Leave a comment', ['class' =>  'btn btn-primary']) !!}
                            </div> 
                        {!! Form::close() !!}
                </div>
            </div>

@stop
ersinkandemir's avatar

Could you control the html output of form to check whether action attribute is set truly.

CedricBongaerts's avatar

@ersinkandemir this is the source:

<form method="POST" action="http://application.dev:8000/posts/1" accept-charset="UTF-8"><input name="_token" type="hidden" value="uvfD8O8l4me4aIgdkSrCe39Ajb8DfuGjsF1AMEpk">

                            <div class="form-group">
                                <textarea class="form-control comments" name="comment" cols="50" rows="10">Comment here...</textarea>
                            </div>

                            <div class="form-group">
                                    <input class="btn btn-primary" type="submit" value="Leave a comment">
                            </div> 
                        </form>
CedricBongaerts's avatar

@ersinkandemir Ok I found out why it wasn't working. I'm working with a slug.. silly me.

But I'm not getting a BadMethodCallException in /home/vagrant/Code/Laravel/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php line 2024:

Call to undefined method Illuminate\Database\Query\Builder::make()

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\User;
use App\Post;
use App\Comment;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class CommentsController extends Controller
{
    
    /**
     * Adds a comment to a specific post
     */
    public function store(Request $request, $slug){

        $post = Post::whereSlug($slug)->first();

        $commentData = array_merge($request->all(), ['user_id' => $request->user()->id]);

        $comment = \App\Comment::make($commentData);

        $post->comments()->save($comment);

        return redirect()->back();
    }
}

This is the line:

$comment = App\Comment::make($commentData);

routes.php

# Comments
    $router->post('posts/{slug}', ['as' => 'comment.store', 'uses' => 'CommentsController@store']);

show.blade.php

@extends('masterpage.app')

@section('content')
        <h1>{{ $post->title }}</h1>
        <h4>{!! nl2br($post->content) !!}</h4>
        @if($post->youtube != '')
            <iframe width="420" height="315" src="http://www.youtube.com/embed/{{$post->youtube}}" frameborder="0" allowfullscreen></iframe>
        @endif

            <div class="panel panel-default">
                    <div class="panel-body">
                        {!! Form::open(['route' => ['comment.store', $post->slug]]) !!}

                            <div class="form-group">
                                {!! Form::Textarea('comment', 'Comment here...', ['class' => 'form-control comments']) !!}
                            </div>

                            <div class="form-group">
                                    {!! Form::submit('Leave a comment', ['class' =>  'btn btn-primary']) !!}
                            </div> 
                        {!! Form::close() !!}
                </div>
            </div>

@stop

The view-source

<form method="POST" action="http://app.dev:8000/posts/my-first-post-odtyvJzm92" accept-charset="UTF-8"><input name="_token" type="hidden" value="IINrYcikpdk3qe8STE6DqEUVjtSwWxduG5u5NGZJ">

                  <div class="form-group">
                      <textarea class="form-control comments" name="comment" cols="50" rows="10">Comment here...</textarea>
                  </div>

                  <div class="form-group">
                          <input class="btn btn-primary" type="submit" value="Leave a comment">
                  </div> 
</form>

rsands's avatar

Shouldn't it be

$comment = new \App\Comment($commentData);

CedricBongaerts's avatar

@rsands when doing this, I get:

QueryException in Connection.php line 636: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (homestead.comments, CONSTRAINT comments_user_id_foreign FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE) (SQL: insert into comments (post_id) values (1))

jekinney's avatar

Instead of request->user_id, may I suggest (assuming user must be logged in) user_id = auth()->id().

rsands's avatar

Can you upload your model and a dump of the data your trying to pass into commentdata?

Im guessing thee line $post = .... is finding a result in the DB?

CedricBongaerts's avatar

@jekinney this gives no difference, but yes, this is true, so I'll keep it like this. @rsands $commentdata returns:

array:3 [▼
  "_token" => "IINrYcikpdk3qe8STE6DqEUVjtSwWxduG5u5NGZJ"
  "comment" => "Comment here..."
  "user_id" => "1"
]

And yes $post is finding the post and adding it to that post (which is also correct) It keeps giving the error with this line:

$comment = \App\Comment::make($commentData);
rsands's avatar

does the ID 1 row exist in users table?

jekinney's avatar

It is failing to reference a user on the user table. As @rsands mentioned if there is a user in the table with applicable id.

billmurrin's avatar

In your database schema, is this valid

->onCascade('update')

Should it be

->onUpdate('cascade')
CedricBongaerts's avatar

@billmurrin when trying this I get: QueryException in Connection.php line 636: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (homestead.comments, CONSTRAINT comments_user_id_foreign FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) (SQL: insert into comments (post_id, updated_at, created_at) values (1, 2015-08-10 07:44:22, 2015-08-10 07:44:22))

billmurrin's avatar

Change post_id to user_id.

Looking at your table schema, your foreign key for your post_id is also set to id on the users table. Shouldn't it be set to id on the posts table? Where is the user_id in your insert statement? Thinking that if you do not supply a user_id it will fail any foreign constraints.

Should it be something like:

insert into comments (user_id, post_id, updated_at, created_at) values (1,1,2015-08-10 07:44:22, 2015-08-10 07:44:22)
cloud4bpm's avatar

Hi @CedricBongaerts, I think the problem is related with the migration:

Schema::create('comments', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')->references('id')->on('users')->onCascade('update')->onDelete('cascade');
            $table->integer('post_id')->unsigned();

            //Here should be on('posts')
            $table->foreign('post_id')->references('id')->on('users')->onCascade('update')->onDelete('cascade');
            $table->text('comment');
            $table->timestamps();
            $table->rememberToken();
        });

I think it should be for the second foreign key the on('posts') table.

hirelaravel's avatar

I am totally new to Laravel development. So I just write code for Comment in Laravel:

Comment View Model:

1 like

Please or to participate in this conversation.