Reputation: 141
I am developing a website using laravel PHP and trying to do a comment system using the following structure:
- Comment 1 (id = 1)
-- Reply 1 (id = 2) (parent_id = 1)
--- Reply 2.1 (id = 3) (parent_id = 2)
-- Reply 2 (id = 4) (parent_id = 1)
I am wondering how would I do a foreach to cover that? Since i don't know how many child comments a comment will have.
Upvotes: 2
Views: 2865
Reputation: 39389
I wouldn’t store comments and replies in a separate table as they’re both comment entities at the end of the day. Simply have a parent_id
column in your comments
table, and you can fetch both comments and replies in one database query as opposed to two.
I assume you also have a foreign key linking a comment to something like a post. You can then fetch all comments for that post ID:
$comments = Comment::latest()->where('post_id', '=', $post->id)->get();
Then sort them based on their parent_id
value:
$comments = $comments->keyBy('parent_id');
You can then iterate over them in your Blade template like this and every iterate, check if there are comments with that comment’s ID as its parent ID:
<!-- Kick-start the loop -->
@foreach($comments[0] as $comment)
@include('partials.comment')
@endforeach
The content of partials/comment.blade.php
<blockquote class="comment">
<p class="comment-body">{{ $comment->body }}</p>
<footer>
<span class="comment-author">{{ $comment->user->name }}</span>,
<time class="comment-date" pubdate="pubdate">{{ $comment->created_at }}</time>
</footer>
</blockquote>
@if(isset($comments[$comment['id']])
@each('partials.comment', $comments[$comment['id'], 'comment')
@endif
Upvotes: 5
Reputation: 843
Table Like:
+------------+-----------+---------+
| comment_id | parent_id | comment |
+------------+-----------+---------+
| 1 | 0 | test |
| 2 | 1 | test1 |
| 3 | 0 | test2 |
| 4 | 0 | test3 |
| 5 | 1 | test4 |
| 6 | 2 | test4 |
| 7 | 4 | test5 |
| 8 | 5 | test6 |
| 9 | 6 | test7 |
| 10 | 4 | test8 |
| 11 | 3 | test9 |
+------------+-----------+---------+
Get first level parent:
$comments = Comment::where('parent_id', '0')->orderBy('comment_id', 'asc')->get();
$result = array();
foreach($comments as $comment){
$list = array();
$list = array_merge($list, [['comment_id' => $comment->comment_id, 'parent_id' => $comment->parent_id, 'comment' => $comment->comment]]);
$result = array_merge($result, $this->get_child_comment($comment->comment_id,0, $list));
}
function get_child_comment($pid,$level,$list=array()) {
$sub_comments = Comment::where('parent_id','=',$pid)->where('comment_id','!=',$pid)->orderBy('comment_id', 'asc')->get();
foreach($sub_comments as $sub_comment){
$space=" "; sigm='-';
for($j=0; $j<=$level; $j++)
{
$space .=$space;
}
for($j=0; $j<=$level; $j++)
{
$space .= $sigm;
}
$sub_comment->comment = html_entity_decode($space, ENT_QUOTES, "utf-8").' '.$sub_comment->comment;
$list = array_merge($list, array(['comment_id' => $sub_comment->comment_id, 'parent_id' => $sub_comment->parent_id, 'comment' => $sub_comment->comment]));
$list = $this->get_child_comment($sub_comment->comment_id, $level+1, $list);
}
return $list;
}
}
return get array.simple print using foreach:
foreach($result as $val) {
echo $val['comment'].'<br>';
}
Output:
test
- test1
-- test4
--- test7
- test4
-- test6
test2
- test9
test3
- test5
- test8
Upvotes: 1
Reputation: 57
You can represent comments in following structure:
$comments = [
(object)[
'id' => 1,
'text' => 'Comment 1',
'children' => [
(object)[
'id' => 2,
'text' => 'Reply 1',
'children' => [
(object)[
'id' => 2,
'text' => 'Reply 1.1'
]
]
],
(object)[
'id' => 4,
'text' => 'Reply 2',
]
]
]
];
And print them using recursive function like this:
function printComments($comments, $prefix = '-') {
foreach ($comments as $comment) {
echo $prefix.$comment->text.'<br>';
isset($comment->children) && printComments($comment->children, $prefix.'-');
}
}
Or calling view recursively in case of Laravel:
@include('comments.view.path') inside of @include('comments.view.path')
For convinient retrieving of comments in the represented structure and generally for working with tree structure I suggest using nested set model and etrepat/baum for Laravel which has toHierarchy() method.
Upvotes: 0