显示使用CakePHP连接到另一个表的记录列表

时间:2012-04-19 19:58:13

标签: php cakephp cakephp-2.1

我有一个存储帖子和主题的应用程序,并使用Topic_Posts表连接它们。

申请的关联如下:

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'
    );
}

当用户查看主题时,例如/topics/view/topicname我想显示包含该主题的所有帖子。

到目前为止,我在我的TopicsController中为视图提供了以下方法:

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);

}

因此我可以使用Posts和TopicPosts,我已将public $uses = array('Topic','TopicPost','Post');添加到控制器的顶部,并使所有模型都可以包含。

所以基本上我需要找到在数据库模型TopicPosts中匹配的帖子,用于我正在查看的主题的id。

3 个答案:

答案 0 :(得分:2)

我无法让它以“正确”的方式工作。我不确定这是不是蛋糕或其他东西的错误,但分页功能只是拒绝让步..正确的方法可能是在你的Post模型中编写自己的paginate函数,有一些信息如何在食谱中做到这一点。

与此同时,我为您提供以下解决方法。它不是最优的(至少不是没有缓存)但它有效。如果遇到性能问题,你可以以正确的方式执行此操作,但在此之前,下面的代码应该这样做。

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');

    // step 1: get post IDs related to your topic
    $postIDs = $this->Topic->TopicPost->find
        (
            'list',
            array
            (
                'fields'        => array('TopicPost.post_id'),
                'conditions'    => array('TopicPost.topic_id' => $topic['Topic']['id'])
            )
        );

    $this->paginate = array
    (
        'Post' => array
        (
            'limit'=>15,
            'conditions'=>array
            (
                'Post.status' => array(1,2),
                // step 2: include them in your paginate conditions
                'Post.id' => $postIDs,
            ),
            'order' => array('Post.datetime'=>'desc'),
        )
    );

    $posts = $this->paginate('Post');

    $this->set('posts', $posts);
}

(请注意我在我的测试中删除了一些内容,因为我的应用中没有一些东西,所以不要忘记把它放回去)

答案 1 :(得分:1)

我认为您的模型关系存在问题,我不明白为什么您在帖子模型上有HABTM关系,当您在TopicPost上实际模仿它(using the Has-many-through method)时模特本身。如果你不想使用内置于蛋糕中的HABTM行为(我不怪你),你应该设置这样的关系:

class PostTopic extends AppModel { // note PostTopic, name should be alphabetical
    public $belongsTo = array('Post', 'Topic');
}

class Post extends AppModel {
    public $hasMany = array('PostTopic');
}

class Topic extends AppModel {
    public $hasMany = array('PostTopic');
}

然后,要获取相关帖子或主题的ID,您只需加载PostTopic课程并进行搜索:

// ie in Post Controller
$this->paginate($this->Post->PostTopic, array('PostTopic.topic_id' => $post['PostTopic']['topic_id']));

我的网站上有类似的设置,用户可以将产品添加到他们的库存中,这是一种HABTM关系,但附加了更多数据。请参阅此处的产品,广告资源和用户模型,了解更复杂的example

答案 2 :(得分:0)

来自问题评论:

  

还要注意数据库结构和关系可以正常工作   可以使用TopicPost提取帖子的主题,所以我知道   工作,它只是获得一个似乎没有的主题的帖子   工作...

是的,因为您为Post->主题设置了HABTM,但没有为Topic-> Post设置。{ 2.0书定义了一个与你的一样的例子(但使用食谱和成分)来描述用例。

  

hasMany和HABTM之间的主要区别在于它之间的链接   HABTM中的模型并不是唯一的。例如,我们即将加入   我们的食谱模型使用HABTM的成分模型。用西红柿   作为我奶奶的意大利面配方的成分不会“用完”   成分。我也可以用它做沙拉食谱。

使用Post(您的标签/类别的名称)Topic也可以这样说。就像他们的例子一样:

  

请记住在Ingredient模型中定义HABTM关联if   您在使用Ingredient模型时想要获取配方数据。

或者,在您的情况下,主题模型。

所以这是你应该使用的模型:

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')
    );
}

class Topic extends AppModel
{
    // Has many posts that belong to topic post join table... jazz
    public $hasAndBelongsToMany = array(
        'Post' => array('with' => 'TopicPost')
    );
}

现在,除非你正在做一些特别的事情,否则你真的不需要TopicPost,但事实并非如此。而且,虽然您可以使用该模型将Topic添加到帖子中(反之亦然),但我建议您使用build in方法处理HABTM保存。有关保存HABTM的详细信息,请查看this page

如果您决定将其删除,请确保为每个模型中的HABTM选项定义连接表和条件per the docs