Reputation: 35
I have add comments to the article, here are all the fields
Schema::create('article_comments', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('article_id');
$table->foreign('article_id')
->references('id')->on('articles')->onDelete('cascade');
$table->string('name');
$table->string('email');
$table->text('text');
$table->string('date');
$table->unsignedBigInteger('comment_id')->nullable();
$table->foreign('comment_id')
->references('id')->on('article_comments')->onDelete('set null');
$table->timestamps();
});
I have 2 blocks of comments, one regular and the second answer to it. The only difference between them is the different classes
This is how I bring them out
Normal comment
<div class="comment-list">
@foreach($article_comments as $article_comment)
<div class="comment-list__item">
<div class="item-card">
<div class="item-card__header">
<div class="item-card__title">
<div class="label">
{!! $article_comment->name !!}
</div>
<div class="data">
{!! date('d F Y', strtotime($article_comment->date)) !!}
</div>
</div>
</div>
<div class="item-card__content">
{!! $article_comment->text !!}
</div>
</div>
</div>
@endforeach
</div>
The reply to him
<div class="comment-sub-list">
<div class="comment-sub-list__item">
<div class="item-card">
<div class="item-card__header">
<div class="item-card__title">
<div class="label">
{!! $article_comment->name !!}
</div>
<div class="data">
{!! date('d F Y', strtotime($article_comment->date)) !!}
</div>
</div>
</div>
<div class="item-card__content">
{!! $article_comment->text !!}
</div>
</div>
</div>
</div>
If the comment_id
field is filled in, then this will be the answer to the comment with this ID, but I can't implement it
I'm trying to type-check for the presence of the comment_id
field and display this comment
$articleCommentsReply = $article_comments->where('comment_id', $article_comment->comment_id)
->whereNotNull('comment_id')
->first();
But in the end, this comment is displayed twice, and one of them is the answer to it
Upvotes: 3
Views: 145
Reputation: 8338
$articleCommentsReply = $article_comments
->where('comment_id', $article_comment->comment_id)
->first();
You are missing the output of your query (in that case ->first()
)
That will return you a single collection and then you should be able to access your property like you attempted.
Also an update based on your comment since you are getting nullable comment_ids you can also filter them out by extending your query to :
$articleCommentsReply = $article_comments
->where('comment_id', $article_comment->comment_id)
->whereNotNull('comment_id')
->first();
Upvotes: 1
Reputation: 6773
based on my understanding of your question here is what you can do to achieve it.
Here I have assumed the article might have many comments and each comment might have zero or many answers to it with maximum one level recursive.
But You can change answers
relationship to just answer
by defining it as hasOne
relationship if you want and instead of using get() can also use first(). Advantage with this hasMany
method is that it will work for both single and multiple related models if you keep it this way.
You can add answers
recursive relation to ArticleComment
model
//in ArticleComment.php
public function answers()
{
return $this->hasMany(ArticleComment::class, 'comment_id', 'id');
}
I assume you already have this relationship defined, if not add this comments
relationship to Article
model.
//in Article.php
public function comments()
{
return $this->hasMany(ArticleComment::class, 'article_id', 'id');
}
Now you can use following query to fetch the articles with comments
. If an answer for that comment exist it will return inside answers
relation. If it is just the comment it will return just the comment inside the comments
relation and answers
will be an empty array.
In the example query below we are looking for comments(with its replies if it has any) of article with id 1. The said article has 2 comments. the first comment has 3 answers to it and second comment does not have any.
$query = Article::where('id', 1)->with(['comments' => function($q) {
$q->whereNull('comment_id')->with('answers');
}]);
$output = $query->get()->toArray();
Here is how the output of this query would look like.
[
{
"id": 1,
"text": "article 1"
"comments": [
{
"id": 1,
"article_id": 1,
"name": "a1q1",
"email": "***",
"text": "Article 1 Comment 1",
"date": "2021-11-22 16:52:11",
"comment_id": null
"answers": [
{
"id": 5,
"article_id": 1,
"name": "a1q1a1",
"email": "***",
"text": "Answer 1 to Article 1 Comment 1",
"date": "2021-11-22 16:52:11",
"comment_id": 1
},
{
"id": 6,
"article_id": 1,
"name": "a1q1a1",
"email": "***",
"text": "Answer 2 to Article 1 Comment 1",
"date": "2021-11-22 16:52:11",
"comment_id": 1
}
]
},
{
"id": 2,
"article_id": 1,
"name": "a1q2",
"email": "***",
"text": "Article 1 Comment 2",
"date": "2021-11-22 16:52:11",
"comment_id": null,
"answers": [
]
}
]
}
]
Note: I think the above method is more efficient if you want to display the article,comments and replies in the same page as it does only one query.
If the answer you are looking for is how to separately check and get specific comments you can use following queries.
just the replies to comment id 1
$repliesToCommentOnly = ArticleComment::where('comment_id', $articleComment->id)
->get()->toArray();
output
[
{
"id": 5,
"article_id": 1,
"name": "a1q1a1",
"email": "***",
"text": "Answer 1 to Article 1 Comment 1",
"date": "2021-11-22 16:52:11",
"comment_id": 1,
"created_at": "2021-11-22T16:52:11.000000Z",
"updated_at": "2021-11-22T16:52:11.000000Z"
},
{
"id": 6,
"article_id": 1,
"name": "a1q1a1",
"email": "***",
"text": "Answer 2 to Article 1 Comment 1",
"date": "2021-11-22 16:52:11",
"comment_id": 1,
"created_at": "2021-11-22T16:52:11.000000Z",
"updated_at": "2021-11-22T16:52:11.000000Z"
}
]
article comment with its replies
$commentWitItsReplies = ArticleComment::where('id', 1)->with('answers')
->get()->toArray();
output
[
{
"id": 1,
"article_id": 1,
"name": "a1q1",
"email": "***",
"text": "Article 1 Comment 1",
"date": "2021-11-22 16:52:11",
"comment_id": null,
"created_at": "2021-11-22T16:52:11.000000Z",
"updated_at": "2021-11-22T16:52:11.000000Z",
"answers": [
{
"id": 5,
"article_id": 1,
"name": "a1q1a1",
"email": "***",
"text": "Answer 1 to Article 1 Comment 1",
"date": "2021-11-22 16:52:11",
"comment_id": 1,
"created_at": "2021-11-22T16:52:11.000000Z",
"updated_at": "2021-11-22T16:52:11.000000Z"
},
{
"id": 6,
"article_id": 1,
"name": "a1q1a1",
"email": "***",
"text": "Answer 2 to Article 1 Comment 1",
"date": "2021-11-22 16:52:11",
"comment_id": 1,
"created_at": "2021-11-22T16:52:11.000000Z",
"updated_at": "2021-11-22T16:52:11.000000Z"
}
]
}
]
Upvotes: 3