0
votes

I have the following relationship:

Post hasMany Comment

Post belongsTo Category

Post HABTM Tag

I want to use the paginate method with those properties:

public $paginate = array(
    'published',
    'limit' => 3,
    'fields' => array(
        'Post.title',
        'Post.date_published',
        'Post.abstract',
        'Post.slug',
        'Category.value',
        'Category.slug'
    )
);

'published' is a customized find query, but that should not matter here. In addition to the infos about a Post and its Category (seen above), I would like to fetch the COUNT of Comments a post has, and the names of all Tags. I.e., I would like to be able to access the data on the View side in a convenient way such as $data['Post']['comment_count'] and $data['Post']['Tag'][0]['name'].

Is there a solution to this which is elegant enough? I know HABTM might be a bit complicated, but I don't even know how to fetch the Comments in the same query, even though it's only a hasMany relationship. Thank you.

1

1 Answers

0
votes

I have found out that using the counterCache parameter in the Comment model as follows

public $belongsTo = array('Post' => array('counterCache' => true));

and adding a comments_count field to the posts table is the easiest solution to fetch the number of Comments for a Post. This will update the table whenever a new Comment is added or deleted.

Concerning Tags, I use the contain array, it can also be used for paginate. I use it like this:

$this -> paginate = array(
        'published',
        'limit' => 3,
        'contain' => array(
            'Category',
            'Tag' => array('fields' => array(
                    'value',
                    'slug'
                ))
        ),
        'fields' => array(
            'Post.title',
            'Post.date_published',
            'Post.abstract',
            'Post.slug',
            'Post.comment_count',
            'Category.value',
            'Category.slug'
        ),
        'conditions' => $conditions,
        'joins' => $joins
    );

Doing it like this, only Categories and the fields value and slug of the Tag model are fetched with every Post request.

There is a special case, when I want to fetch all Posts with a certain Tag. Remember, it's a HABTM relation. I came across this useful model method by Geoff Garbers

Adding it to AppModel, it allows to call hasAndBelongsToMany, and automates the tedious process of defining joins for the paginate method. As you can see above, they are added via the $joins array, which is generated with the above method as such:

$joins = $this -> Post -> generateHabtmJoin('Tag');

Now it's easily possible to define conditions such as:

$conditions = array('Tag.slug' => $this -> request -> params['tag']);

Which will only fetch Posts that have a certain Tag.slug.

Hope this helps somebody.