如何在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中,我将从视图遍历一个模型方法。