Search code examples
mysqlcakephphas-manybelongs-to

Relate Comments with themselves


I'm new to cakePHP and the whole MVC architecture.

I want to build a Reddit-like comment system where one Comment hasMany Comment(s) but also one Comment belongsTo (only) one Comment.

It is the usual comment section where one comment can has a reply to that comment and the reply can have its own reply(ies) etc:

Nice article!
|
-- I didn't like it!
   |
   -- Well, you should have!
   |
   -- Yeah me neither!

Right now I have only set the 'hasMany' relationship like this:

class Comment extends AppModel {
    public $hasMany = array(
        'Comment' => array(
            'className' => 'Comment',
            'foreignKey' => 'comment_id',
            'dependent' => FALSE
        )
    );
}

comment_id will contain the id of the parent comment (NULL if comment has no parent).

When I ask cakePHP to return me all the comments that belong to a specific post, it returns me this (I've manually added the comments):

 Array
(
    [0] => Array
        (
            [Comment] => Array
                (
                    [id] => 2
                    [post_id] => 4
                    [comment_id] => 4
                    [body] => Child of 4
                    [created] => 2015-01-31 18:01:27
                    [modified] => 2015-01-31 18:01:27
                    [0] => Array
                        (
                            [id] => 3
                            [post_id] => 4
                            [comment_id] => 2
                            [body] => Child of 2
                            [created] => 2015-01-01 00:00:00
                            [modified] => 2015-01-16 00:00:00
                        )

                    [1] => Array
                        (
                            [id] => 5
                            [post_id] => 4
                            [comment_id] => 2
                            [body] => 2nd child of 2
                            [created] => 2015-01-14 00:00:00
                            [modified] => 2015-01-28 00:00:00
                        )

                )

        )

    [1] => Array
        (
            [Comment] => Array
                (
                    [id] => 3
                    [post_id] => 4
                    [comment_id] => 2
                    [body] => Child of 2
                    [created] => 2015-01-01 00:00:00
                    [modified] => 2015-01-16 00:00:00
                )

        )

    [2] => Array
        (
            [Comment] => Array
                (
                    [id] => 4
                    [post_id] => 4
                    [comment_id] => 
                    [body] => This is the parent of all
                    [created] => 2015-01-21 00:00:00
                    [modified] => 2015-01-30 00:00:00
                    [0] => Array
                        (
                            [id] => 2
                            [post_id] => 4
                            [comment_id] => 4
                            [body] => Child of 4
                            [created] => 2015-01-31 18:01:27
                            [modified] => 2015-01-31 18:01:27
                        )

                )

        )

    [3] => Array
        (
            [Comment] => Array
                (
                    [id] => 5
                    [post_id] => 4
                    [comment_id] => 2
                    [body] => 2nd child of 2
                    [created] => 2015-01-14 00:00:00
                    [modified] => 2015-01-28 00:00:00
                )

        )

)

In my understanding, it fetches all the comments and then for each one it re-searches the database for the ones that have 'children'.

What is the correct way so as to make cakePHP return a 'ready' array of arrays of comments like this:

Array
(
    [0] => Array
        (
            [Comment] => Array
                (
                    [id] => 4
                    [post_id] => 4
                    [comment_id] => 
                    [body] => This is the parent of all
                    [created] => 2015-01-21 00:00:00
                    [modified] => 2015-01-30 00:00:00
                    [0] => Array
                        (
                            [id] => 2
                            [post_id] => 4
                            [comment_id] => 4
                            [body] => Child of 4
                            [created] => 2015-01-31 18:01:27
                            [modified] => 2015-01-31 18:01:27
                            [0] => Array
                            (
                                [id] => 5
                                [post_id] => 4
                                [comment_id] => 2
                                [body] => 2nd child of 2
                                [created] => 2015-01-14 00:00:00
                                [modified] => 2015-01-28 00:00:00
                            )
                            [1] => Array
                            (
                                [id] => 5
                                [post_id] => 4
                                [comment_id] => 2
                                [body] => 2nd child of 2
                                [created] => 2015-01-14 00:00:00
                                [modified] => 2015-01-28 00:00:00
                            )

                        )
                )
        )
)

Solution

  • You might want to use find('threaded'). You can also look into the tree behavior.