4

我有一个存储帖子和主题并使用 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 匹配的帖子。

4

3 回答 3

2

我只是无法让它以“正确”的方式工作。我不确定这是否是蛋糕中的错误或其他什么,但 paginate 函数只是拒绝让步。. 正确的方法可能是在 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);
}

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

于 2012-04-19T22:11:38.237 回答
1

我认为你的模型关系有问题,我不明白为什么你在帖子模型上有一个 HABTM 关系,当你实际上在模型本身上模拟这个(使用 Has-many-through 方法)时。TopicPost如果你不想使用 cake 内置的 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 关系,但附加了更多数据。有关更复杂的示例,请参见此处的产品、库存和用户模型。

于 2012-04-23T12:05:26.580 回答
0

从问题评论:

还要注意数据库结构和关系工作正常,因为我可以使用 TopicPost 将主题拉到一个帖子中,所以我知道这是可行的,它只是为一个似乎不起作用的主题获取帖子......

对,因为您为 Post->Topic 设置了HABTM,但没有为 Topic->Post 设置。2.0 书定义了一个与您的示例类似的示例(但使用配方和成分)来描述用例。

hasMany 和 HABTM 之间的主要区别在于,HABTM 中的模型之间的链接不是排他的。例如,我们即将使用 HABTM 将我们的食谱模型与成分模型结合起来。使用西红柿作为我奶奶的意大利面食谱的配料不会“用完”配料。我也可以用它来做沙拉食谱。

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

如果您想在使用成分模型时获取配方数据,请记住在成分模型中定义 HABTM 关联。

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

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

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,但这很好。而且,尽管您可以使用该模型将Topics 添加到帖子中(反之亦然),但我建议您使用内置方法来处理 HABTM 保存。查看此页面以获取有关保存 HABTM 的详细信息。

如果您决定删除它,请确保根据文档为每个模型中的 HABTM 选项定义连接表和条件

于 2012-04-23T17:38:17.247 回答