如何在CakePHP中找到包含的模型中的类别

如何在CakePHP中找到包含的模型中的类别,cakephp,Cakephp,我最近在这里问了一个关于。现在,我可以在我搜索的类别中搜索帖子了 现在,我的问题是如何检索每篇文章的类别。有时,一篇文章在此查询中有一个或多个类别: $this->set('posts', $this->Category->find( 'first', array( 'conditions' => array( 'Category.uri' => $uri ), 'contain

我最近在这里问了一个关于。现在,我可以在我搜索的类别中搜索帖子了

现在,我的问题是如何检索每篇文章的类别。有时,一篇文章在此查询中有一个或多个类别:

$this->set('posts', $this->Category->find(
    'first',
    array(
        'conditions' => array(
            'Category.uri' => $uri
        ),
        'contain' => array('Post')
    )
));
我会想象这样的情况:

$this->set('posts', $this->Category->find(
    'first',
    array(
        'conditions' => array(
            'Category.uri' => $uri
        ),
        'contain' => array('Post' => array(
            'contain' => 'Category'
        ))
    )
));
categories
id name
1  holidays
2  destinations

posts
id title
1  I am a post
2  I am another post

categories_posts
post_id category_id
1       1
2       2
2       1
$this->find('first', array(
        'conditions' => array('Category.uri' => $uri),
        'contain' => array(
            'Post' => array(
                'Category' => array(
                    'Tag' => array('Author')
                )
            )
        )
    ));
Array
(
    [Category] => Array
        (
            [id] => 3
            [name] => festivals
            [uri] => festivals
            [created] => 2010-11-25 20:43:03
            [modified] => 2010-11-25 20:43:03
        )

    [Post] => Array
        (
            [0] => Array
                (
                    [id] => 28
                    [title] => A Post
                    [Categories] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 3
                                    [name] => festivals
                                    [uri] => festivals
                                    [created] => 2010-11-25 20:43:03
                                    [modified] => 2010-11-25 20:43:03
                                )

                            [1] => Array
                                (
                                    [id] => 4
                                    [name] => destinations
                                    [uri] => destinations
                                    [created] => 2010-11-28 13:04:52
                                    [modified] => 2010-11-28 13:04:52
                                )

                        )

                )
)
// From the CategoriesController
$this->Category->Post->find('all', array(
    'joins' => array(
        array(
            'table' => 'categories_posts',
            'alias' => 'CategoryFilter',
            'type' => 'inner',
            'conditions' => array(
                'CategoryFilter.post_id = Post.id'
            )
        ),
        array(
            'table' => 'categories',
            'alias' => 'CategoryUriFilter',
            'type' => 'inner',
            'conditions' => array(
                'CategoryUriFilter.id = CategoryFilter.category_id'
            )
        )
    ),
    'conditions' => array(
        'CategoryUriFilter.uri' => $uri
    ),
    'contain' => array('Category')
));
这是我的模特的样子

// Category Model
class Category extends AppModel {
    var $name = 'Category';
    var $hasAndBelongsToMany = array(
        'Post' => array(
            'className' => 'Post'
        )
    );
    var $actsAs = array('Containable');
}

// Post Model
    class Post extends AppModel {
        var $name = 'Post';
        var $hasAndBelongsToMany = array(
            'Category' => array(
                'className' => 'Category'
            )
        );
        var $actsAs = array('Containable');
        var $virtualFields = array(
            'date_posted' => 'DATE_SUB(Post.created, INTERVAL 7 DAY)'
        );
    }
示例数据如下所示:

$this->set('posts', $this->Category->find(
    'first',
    array(
        'conditions' => array(
            'Category.uri' => $uri
        ),
        'contain' => array('Post' => array(
            'contain' => 'Category'
        ))
    )
));
categories
id name
1  holidays
2  destinations

posts
id title
1  I am a post
2  I am another post

categories_posts
post_id category_id
1       1
2       2
2       1
$this->find('first', array(
        'conditions' => array('Category.uri' => $uri),
        'contain' => array(
            'Post' => array(
                'Category' => array(
                    'Tag' => array('Author')
                )
            )
        )
    ));
Array
(
    [Category] => Array
        (
            [id] => 3
            [name] => festivals
            [uri] => festivals
            [created] => 2010-11-25 20:43:03
            [modified] => 2010-11-25 20:43:03
        )

    [Post] => Array
        (
            [0] => Array
                (
                    [id] => 28
                    [title] => A Post
                    [Categories] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 3
                                    [name] => festivals
                                    [uri] => festivals
                                    [created] => 2010-11-25 20:43:03
                                    [modified] => 2010-11-25 20:43:03
                                )

                            [1] => Array
                                (
                                    [id] => 4
                                    [name] => destinations
                                    [uri] => destinations
                                    [created] => 2010-11-28 13:04:52
                                    [modified] => 2010-11-28 13:04:52
                                )

                        )

                )
)
// From the CategoriesController
$this->Category->Post->find('all', array(
    'joins' => array(
        array(
            'table' => 'categories_posts',
            'alias' => 'CategoryFilter',
            'type' => 'inner',
            'conditions' => array(
                'CategoryFilter.post_id = Post.id'
            )
        ),
        array(
            'table' => 'categories',
            'alias' => 'CategoryUriFilter',
            'type' => 'inner',
            'conditions' => array(
                'CategoryUriFilter.id = CategoryFilter.category_id'
            )
        )
    ),
    'conditions' => array(
        'CategoryUriFilter.uri' => $uri
    ),
    'contain' => array('Category')
));
我正在从假期中取回邮件

Array
(
    [Category] => Array
        (
            [id] => 3
            [name] => holidays
            [uri] => holidays
            [created] => 2010-11-25 20:43:03
            [modified] => 2010-11-25 20:43:03
        )

    [Post] => Array
        (
            [0] => Array
                (
                    [id] => 1
                    [title] => I am a post
                ),
            [1] => Array
                (
                    [id] => 2
                    [title] => I am a another post
                )
        )
)
问题是,其中1个职位分为两类。我希望也能得到这些信息。

结束。试试这个:

$this->set('posts', $this->Category->find(
    'first',
    array(
        'conditions' => array(
            'Category.uri' => $uri
        ),
        'contain' => array('Post' => array('Category'))
    )
));
切线 这样编写控制器代码有问题:

它会使控制器方法膨胀,使控制器可读性降低。 它防止您在不同的控制器之间重复使用业务逻辑。 通过将find调用移动到模型方法,可以令人满意地纠正这些问题:

// Categories Controller
$this->set('posts', $this->Category->get_posts_with_cats($uri));

// Category Model
function get_posts_with_cats($uri) {
    $this->find('first', array(
        'conditions' => array('Category.uri' => $uri),
        'contain' => array('Post' => array('Category'))
    ));
}
这将使您的代码更加出色:

控制器很好,而且可读性很强。 现在,您可以从任何关联的模型调用相同的方法。例如,在PostsController中,您可以调用:$this->Post->Category->get\u posts\u with\u cats$uri;。您的代码现在是。 切线2 在学习了如何嵌套可包含模型(如我向您展示的)之后,您可能会在将来尝试这样做:

$this->set('posts', $this->Category->find(
    'first',
    array(
        'conditions' => array(
            'Category.uri' => $uri
        ),
        'contain' => array('Post' => array(
            'contain' => 'Category'
        ))
    )
));
categories
id name
1  holidays
2  destinations

posts
id title
1  I am a post
2  I am another post

categories_posts
post_id category_id
1       1
2       2
2       1
$this->find('first', array(
        'conditions' => array('Category.uri' => $uri),
        'contain' => array(
            'Post' => array(
                'Category' => array(
                    'Tag' => array('Author')
                )
            )
        )
    ));
Array
(
    [Category] => Array
        (
            [id] => 3
            [name] => festivals
            [uri] => festivals
            [created] => 2010-11-25 20:43:03
            [modified] => 2010-11-25 20:43:03
        )

    [Post] => Array
        (
            [0] => Array
                (
                    [id] => 28
                    [title] => A Post
                    [Categories] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 3
                                    [name] => festivals
                                    [uri] => festivals
                                    [created] => 2010-11-25 20:43:03
                                    [modified] => 2010-11-25 20:43:03
                                )

                            [1] => Array
                                (
                                    [id] => 4
                                    [name] => destinations
                                    [uri] => destinations
                                    [created] => 2010-11-28 13:04:52
                                    [modified] => 2010-11-28 13:04:52
                                )

                        )

                )
)
// From the CategoriesController
$this->Category->Post->find('all', array(
    'joins' => array(
        array(
            'table' => 'categories_posts',
            'alias' => 'CategoryFilter',
            'type' => 'inner',
            'conditions' => array(
                'CategoryFilter.post_id = Post.id'
            )
        ),
        array(
            'table' => 'categories',
            'alias' => 'CategoryUriFilter',
            'type' => 'inner',
            'conditions' => array(
                'CategoryUriFilter.id = CategoryFilter.category_id'
            )
        )
    ),
    'conditions' => array(
        'CategoryUriFilter.uri' => $uri
    ),
    'contain' => array('Category')
));
好消息是什么?只要定义了所有这些关系,就可以从上述方法中获得所需的模型数据

可怕的消息?CakePHP不知道如何为这样的深层关联优化查询。因此,随着数据库的增长,最终将有几十个(如果不是几百个,如果不是数千个)SELECT查询进入数据库,如果不是停止的话,将有效地使应用程序处于爬行状态


设计CakePHP的好手们正在为CakePHP 2.0开发一种更好的可容纳行为,但您必须等到那时才能达到这种精度

实际上,我这样做是为了得到我想要的:

function getPostsFromCategory($uri) {
        return $this->populatePosts($this->find(
            'first',
            array(
                'conditions' => array(
                    'Category.uri' => $uri
                ),
                'contain' => array('Post' => array('Category'))
            )
        ));
    }

    function populatePosts($categoryPosts) {
        $posts = $categoryPosts['Post'];
        $count = count($categoryPosts['Post']);

        for ($i = 0; $i < $count; $i++) {
            $categories = $this->Post->find('first', array('conditions' => array('Post.id' => $categoryPosts['Post'][$i]['id']),
            'contains' => array('Category')));

            // unset($categories['Post']);
            foreach ($categories['Category'] as $cat) {
                $categoryPosts['Post'][$i]['Categories'][] = $cat;
            }
            unset($categories);
        }
        return $categoryPosts;
    }

我留下我的另一个答案,因为它包含了很多好的信息给那些可能偶然发现它的人。为了更优雅地解决你的问题?您将需要翻转其头部的查找,并使用特殊连接从Post模型中进行搜索,如下所示:

$this->set('posts', $this->Category->find(
    'first',
    array(
        'conditions' => array(
            'Category.uri' => $uri
        ),
        'contain' => array('Post' => array(
            'contain' => 'Category'
        ))
    )
));
categories
id name
1  holidays
2  destinations

posts
id title
1  I am a post
2  I am another post

categories_posts
post_id category_id
1       1
2       2
2       1
$this->find('first', array(
        'conditions' => array('Category.uri' => $uri),
        'contain' => array(
            'Post' => array(
                'Category' => array(
                    'Tag' => array('Author')
                )
            )
        )
    ));
Array
(
    [Category] => Array
        (
            [id] => 3
            [name] => festivals
            [uri] => festivals
            [created] => 2010-11-25 20:43:03
            [modified] => 2010-11-25 20:43:03
        )

    [Post] => Array
        (
            [0] => Array
                (
                    [id] => 28
                    [title] => A Post
                    [Categories] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 3
                                    [name] => festivals
                                    [uri] => festivals
                                    [created] => 2010-11-25 20:43:03
                                    [modified] => 2010-11-25 20:43:03
                                )

                            [1] => Array
                                (
                                    [id] => 4
                                    [name] => destinations
                                    [uri] => destinations
                                    [created] => 2010-11-28 13:04:52
                                    [modified] => 2010-11-28 13:04:52
                                )

                        )

                )
)
// From the CategoriesController
$this->Category->Post->find('all', array(
    'joins' => array(
        array(
            'table' => 'categories_posts',
            'alias' => 'CategoryFilter',
            'type' => 'inner',
            'conditions' => array(
                'CategoryFilter.post_id = Post.id'
            )
        ),
        array(
            'table' => 'categories',
            'alias' => 'CategoryUriFilter',
            'type' => 'inner',
            'conditions' => array(
                'CategoryUriFilter.id = CategoryFilter.category_id'
            )
        )
    ),
    'conditions' => array(
        'CategoryUriFilter.uri' => $uri
    ),
    'contain' => array('Category')
));

返回的数组的格式有点不同,但它应该包含您要查找的所有数据。

很抱歉,它确实有效。我在containable参数中嵌套数组的方式是正确的。如果它不起作用,请检查您的关系声明。您可能在Category模型中定义了$hasandbelongtomany,但在Post模型中没有定义。实际上,即使没有新的containable参数,它也会执行相同的查询。我已经添加了更多信息。这种方法似乎是合乎逻辑的,但没有任何作用。我可能错过了什么。您是否忘记将Containable添加到组件列表中?erg。。。也许不是。让我来分析一下你的新信息。只是想澄清一下:你只想返回那些有两个或更多类别的帖子?或者,是否要返回包含2个或更多帖子的类别?我要返回类别内的帖子。我还希望每个帖子都能提供关于他们的分类的信息。应该是一个或两个。如果这不可能,有什么方法可以做到吗?在CodeIgniter中,我将从视图遍历一个模型方法。