I have an application that stores Posts and Topics and joins them using a Topic_Posts table.
The associations for the application are as follows:
Post.php
class Post extends AppModel
{
public $name = 'Post';
public $belongsTo = 'User';
public $hasMany = array('Answer');
// Has many topics that belong to topic post join table... jazz
public $hasAndBelongsToMany = array(
'Topic' => array('with' => 'TopicPost')
);
}
Topic.php
class Topic extends AppModel
{
public $hasMany = array(
'TopicPost'
);
}
TopicPost.php
class TopicPost extends AppModel {
public $belongsTo = array(
'Topic', 'Post'
);
}
When a user views a topic e.g. /topics/view/topicname I want to show all the posts that contain that Topic.
So far I have the following method in my TopicsController for the view:
public function view ( $slug )
{
$topic = $this->Topic->find('first', array('conditions'=>array('Topic.slug'=>$slug)));
$this->set('topic', $topic);
$this->set('title_for_layout', $topic['Topic']['title'] . ' – Topics');
$this->paginate = array
(
'Post' => array
(
'limit'=>15,
'conditions'=>array
(
'Post.status'=>array(1,2),
'TopicPost.topic_id' => $topic['Topic']['id'],
),
'order'=>array('Post.datetime'=>'desc'),
'contain'=>array('User'=>'Profile', 'TopicPost')
)
);
$posts = $this->paginate('Post'); // this one
$this->set('posts', $posts);
}
And so that I can use Posts and TopicPosts I have added: public $uses = array('Topic','TopicPost','Post'); to the top of the controller and made all models act as containable.
So basically I need to find Posts that have a match in the database model TopicPosts for the id of the topic I’m viewing.
I just couldn’t get it to work the “proper” way. I’m not sure if this is a bug in cake or something, but the paginate function simply refuses to budge.. The proper way to do this would probably be to write your own paginate function in your Post model, there is some info on how to do that in the cookbook.
Meanwhile, I offer you the workaround below. It’s not optimal (at least not without caching) but it works. You can do it the proper way when/if you run into performance problem, but until then, this code below should do it.
(Please note that I’ve stripped some of the stuff in my tests as I didn’t have some of the stuff in your app, so don’t forget to put it back)