0
votes

I created a comments system in my app which is now attached to my articles->view. One of the features of the comments controller is to be able to allow users to respond to a comment (one level) and being able to create many children comments for a particular comment. Everything is connected thru parent_id.

Right now, when I open an article I use foreach $comments as $comment to retrieve all comments related to the article and in articles_controller.php I assign the $comments variable to find all comments related to the article.

What is the best way to get the children comments of $comment and display it on my view?

The way I am approaching it is to have a function that returns a list of children comments based on $comments->id and display it under $comment per figure below... This seems to be time consuming as a call will be made to this function(ie. childrenComments($id)) for each comment and can definitely bog down the server.

Does anyone know of a better way to use the parent_id relation and save some CPU time?

Example - "Children" comment is manually added at this time

thank you all for your help.

3

3 Answers

0
votes

If its a nested set tree order by the "left" field. If you have just the parent_id I think order them by creation date should work too and fetch all records related to the foreign key of whatever they belong to.

0
votes

I could not figure out how to do this, maybe the right way, so I opted to use elements to accomplish this. Basically, at each iteration of foreach $comments, I make a call to childrenComments element to check if there are children comments for the current $comment['Comment']['id']. If there are comments, I use for each to display each comment below its parent comment. See some code below....

Code in articles_controller.php

function childrenComments($id = null){
    $comments = $this->Article->Comment->find(
        'all',
        array(
            'fields' => array(
                'Comment.id',
                'Comment.comment',
                'User.username',
                'User.image'
            ),
            'conditions' => array(
                'Comment.parent_id =' => $id,
                'Comment.approved =' => 1
            )
        )
    );
    return $comments;
}

Element childrenComments.ctp

<div style="width:100%;">
<div>
    <?php
    $childrenComments = $this->requestAction('/articles/childrenComments/'.$id);
    foreach ($childrenComments as $childrenComment){
    ?>
    <table cellpadding=0 cellspacing=0>
        <tr>
            <td>
                <img style="width:30px;margin-right:5px" src="<?php echo $childrenComment['User']['image'];?>">
            </td>
            <td width=100% style="padding-left:10px;">
                <?php
                    echo $childrenComment['Comment']['comment'];
                ?>
            </td>
        </tr>
    </table>
    <?php
        }
    ?>
</div>

Code in my /articles/view.ctp

<?php 
     foreach($comments as $comment){
 ...
 //Code are placed here to display each parent comment
     ...

         //This will iterate and display all children comments
         echo $this->element('childrenComments',array('id' => $comment['Comment']['id']));
     }
?>

And the result is: Actual result

0
votes

I found a solution not to use RequestAction for indent comments. Basically, in the view I display comments without replies, with an Element. I pass through this element the whole comments array. In this array, if we have a comment with "parent ID" matching the comment we are displaying, there is a foreach that loops again, and so on...

In Post/view.ctp :

foreach ($post['Comment'] as $comment) {
   echo $this->element('comment', array('comments'=> $post['Comment'], 'id'=> $comment['id'], 'comment'=> $comment, 'user'=> $comment['User'], 'postId'=> $post['Post']['id'], 'level'=> '1'));
}

// Notice the whole comments array passed in the element 'comments'=> $post['Comment']

In Element/comment.ctp :

// After the code that displays comment content

foreach ($comments as $comm) {
  if ( $comm['parent_id'] == $comment['id'] ) {
    echo $this->element('comment', array('comments'=> $comments, 'id'=> $comm['id'], 'comment'=> $comm, 'user'=> $comm['User'], 'postId'=> $postId, 'level'=> $level));
  }
}