3

I've got a system in which there are users who create posts and they can comment on posts as well.

Here are migrations:

users table

public function up()
{
    Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('gender')->default('Male');
    $table->string('email')->unique();
    $table->string('city')->default('Peshawar');
    $table->string('avatar')->default('user.png');
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});
}

posts table

    public function up()
{
    Schema::create('posts', function (Blueprint $table) {


        $table->bigIncrements('p_id');
        $table->text('description');
        $table->integer('user_id');   // this should be user id nothing else
        $table->timestamps();

    });
}

comments table

    public function up()
{
    Schema::create('comments', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->integer('user_id'); // who has done comment
        $table->integer('post_id');  // on which post comment has been done
        $table->text('body');
        $table->timestamps();
    });
}

Models

User Model

class User extends Authenticatable{
use Notifiable;

// custom function used for relationshisp
// user can have many posts

public function posts(){
    return $this->hasMany('App\Post');
}

// user can have many comments as well

public function comments(){
    return $this->hasMany('App\Comment');
}

}

Post Model

class Post extends Model{
   // posts belongs to one user
   public function user(){
    return $this->belongsTo('App\User');
  }


   public function comments(){
    return $this->hasMany('App\Comment');
   } 

 }

Comment Model

class Comment extends Model

{

// doing this we could insert data into comment table
protected $fillable =['user_id','post_id','body'];
// we need two(2) relations here
// relation of comment with post

// relation of comment with user

// 1. comment belongs to one post

public function post(){
    return $this->belongsTo('App\Post');
}

// 2. comment belongs to a user as well

public function user(){
    return $this->belongsTo('App\User');
}

}

route

Route::get('/home', 'HomeController@index')->name('home');

Here is the index method in HomeController

public function index(){
    $posts = Post::with('comments')->get();
    // $comments = Comment::all();

    return view('home')->with( array('posts'=>$posts ) );
}

Problem

So when I visit /home I want to get all posts with their comments.

As you can see I've retrieved posts with their comment like this:

$posts = Post::with('comments')->get();

And then I'm passing it to home.blade.php. Here is what I'm doing at home.blade.php to achieve this task.

View /home.blade.php

@foreach($posts as $post)

     <h4 class="media-heading">{{$post->user->name}}</h4>
     <small>{{$post->created_at}}</small>

     <p>{{$post->description}}</p>

     <!-- trying to retrieve comments with each post -->

             @if (count($post->comments))
                  @foreach($post->commnents as $comment)
                      <small>$comment->body</small>
                   @endforeach
             @else 
                  No comments Found
             @endif 




 @endforeach

It gives me this error

Undefined variable: post (View: F:\application\resources\views\home.blade.php)

Keeping in mind those models and their relationships with each other, am I doing it in the wrong way to retrieve comments for each post? If so, how can I get all the posts with their comments and when there are no comments it should say no comments found.

Here is what the result return by dd($posts) dd($posts) returning this, have a look at the comments field, that is empty.

The network tab is showing the following this Please help, Thanks to everyone.

BPDESILVA
  • 2,040
  • 5
  • 15
  • 35
contributor
  • 143
  • 3
  • 12
  • Look into the trace of the error in which line is the exception. – porloscerros Ψ Jun 16 '19 at 07:19
  • Also, you have a typo here: `@foreach($post->commnents` – porloscerros Ψ Jun 16 '19 at 07:20
  • it highlights the problem in `if(count($post->comments))` – contributor Jun 16 '19 at 07:29
  • try to `@php dd($posts); @endphp` at the top of home.blade.php, then you can see what is inside the posts. – Muhammad Jun 16 '19 at 07:30
  • try to fix the typo as porloscerros said. – Muhammad Jun 16 '19 at 07:32
  • where is the typo ? @porloscerrosΨ – contributor Jun 16 '19 at 07:33
  • in the foreach `$post->commnents` must be `$post->comments` – porloscerros Ψ Jun 16 '19 at 07:39
  • I fixed that,that error is solved , but now I can't get comments , it says `no comments found` meaning that `if` block fails, although I have comments in comments table @porloscerrosΨ – contributor Jun 16 '19 at 07:43
  • `dd($posts)` shows a collection of `posts` with some internal arrays @Muhammad – contributor Jun 16 '19 at 07:46
  • but is there a comments field? – porloscerros Ψ Jun 16 '19 at 07:51
  • another thing, in the query you are not bringing the related user, it is strange that you do not get an error when you want to show it in the view `{{$post->user->name}}`. Add 'user' inside the with: `$posts = Post::with(['user', 'comments'])->get();` – porloscerros Ψ Jun 16 '19 at 07:53
  • no, please have a look at the migrations @porloscerrosΨ – contributor Jun 16 '19 at 07:53
  • ok, but the related comments will be inside a comments field of the Post Object – porloscerros Ψ Jun 16 '19 at 07:56
  • I've added screenshot of what the `dd($posts)` is returning, please have a look at the post, you can see the `comment` field, that is empty, are you talking about that ? @porloscerrosΨ – contributor Jun 16 '19 at 08:04
  • how would you try to get all the comments with each posts and then show it in the view ? please share that so that I'll get an idea, am I doing it correctly ? @porloscerrosΨ – contributor Jun 16 '19 at 08:13
  • Well, clearly the comments relation is empty. Is it the same for all Posts? I'm seeing that in the migrations you did not add the foreign keys. – porloscerros Ψ Jun 16 '19 at 08:16
  • Yes , I didn't add any kind of foreign keys , because somewhere I read that I don't need that. Plus I'm just a beginner in laravel, _Well, clearly the comments relation is empty. Is it the same for all Posts_? A comments table is kind of pivot table with `user_id` and `post_id` as foreign keys but I didn't added them as `foreign keys` is that a problem ? – contributor Jun 16 '19 at 08:23
  • Creating the foreign key constraints, will force referential integrity at the database level. So, for example, if you try to add a comment with the wrong post_id, will throw you an exception. The answer posted by MekjkrhG makes sense, take a look at it – porloscerros Ψ Jun 16 '19 at 08:31

2 Answers2

2

its probably because of this..

public function up()
{
    Schema::create('posts', function (Blueprint $table) {


        $table->bigIncrements('p_id'); <---
        $table->text('description');
        $table->integer('user_id');   // this should be user id nothing else
        $table->timestamps();

    });
}

any reason why you are using p_id instead of id? relations work so that id of post is matched to the post_id in the comments table.. if you using this u have to specify this custom key when you are creating the relationship..

check out https://laravel.com/docs/5.8/eloquent-relationships#defining-relationships

MekjkrhG
  • 211
  • 1
  • 8
  • But that leads to an another problem , now ajax commenting is not working ! @MekjkrhG – contributor Jun 16 '19 at 09:36
  • Here is the code link, I've the same code till now , but commenting on the fly is not working, before the fix you suggested it was working fine; https://stackoverflow.com/questions/56599519/get-comments-on-a-post-from-database-using-ajax?noredirect=1#comment99778179_56599519 – contributor Jun 16 '19 at 09:41
  • ah reminder.. if you changed the migration from p_id to id.. you have to update the codes which were using p_id to id.. else it wont work. do u get any errors? – MekjkrhG Jun 16 '19 at 09:47
  • even the comment is not storing into into the DB, after this change, the code is there that I've provided the link @MekjkrhG – contributor Jun 16 '19 at 09:52
  • did u rollback the migration and change the p_id to id? and after that migrate again? – MekjkrhG Jun 16 '19 at 09:53
  • Yes but I manually change `p_id` to `id` from `phpmyadmin`. I got this in console : `500 Internal Server Error 214ms`, in firefox `XHR` tab – contributor Jun 16 '19 at 10:00
  • ah thats not the right way to do it.. you can either rollback the migration and re-migrate after changing the value.. or rename the column from p_id to id.. check rename column here.. https://laravel.com/docs/5.8/migrations#column-modifiers but since u have already done update the post table migration file from p_id to id. change all the $post->p_id to $post->id like in your form post `
    ` to `
    ` and any other place where you have used p_id to id.
    – MekjkrhG Jun 16 '19 at 10:16
  • Yesh I've already changed the `p_id` to `id` then I changed that in `phpmyadmin` manually. And also changed other places from `p_id` to `id`, still same problem – contributor Jun 16 '19 at 11:03
  • can u further explore the console error `500 Internal Server Error 214ms` from network tab. it will show the exact error – MekjkrhG Jun 16 '19 at 11:23
1

Try passing your post custom key as third argument to the relation:

Comment Model

public function post(){
    return $this->belongsTo('App\Post', 'post_id', 'p_id');
}

Maybe a better option will be, change the key of the table posts to 'id' to agree with the conventions of Laravel. Create a new migration and run it.

Schema::table('posts', function (Blueprint $table) {
    $table->renameColumn('p_id', 'id');
});

Another option would be, creating the foreign key constraints, to force referential integrity at the database level:

posts table

public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->bigIncrements('p_id');
        $table->text('description');
        $table->integer('user_id')->unsigned();
        $table->timestamps();

        $table->foreign('user_id')->references('id')->on('users');
    });
}

comments table

public function up()
{
    Schema::create('comments', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->integer('user_id')->unsigned(); 
        $table->integer('post_id')->unsigned();  
        $table->text('body');
        $table->timestamps();

        $table->foreign('user_id')->references('id')->on('users');
        $table->foreign('post_id')->references('p_id')->on('posts');
    });
}

You will have to rollback and re-run the migrations (you will lose the data saved in DB).

porloscerros Ψ
  • 4,808
  • 2
  • 11
  • 20
  • Note the two firsts options are the suggested by MekjkrhG's answer. Feel free to [upvote](https://stackoverflow.com/help/someone-answers) the answers if them helped to solve your problem ;) – porloscerros Ψ Jun 16 '19 at 09:10