带有“hasAndBelongsToMany”的控制器的 CakePHP 条件查询

Posted

技术标签:

【中文标题】带有“hasAndBelongsToMany”的控制器的 CakePHP 条件查询【英文标题】:CakePHP conditional query with controller that 'hasAndBelongsToMany' 【发布时间】:2011-05-13 01:56:06 【问题描述】:

我为这个可怕的标题道歉,我想不出如何解释我的问题。

在我的数据库中,我有以下表格,articlestagsarticles_tags。一篇文章可以有很多标签。

目前我可以抓取所有带有所有标签的文章,但我希望能够根据标签找到文章。

我的选择很简单:

$articles = $this->Article->find('all', array(
    // extra condition to check for tag, maybe?
    'conditions'    => array('Article.status' => 'active'), 
    'limit'         => $this->articles_per_page,
    'offset'        => ($page_num-1)*$this->articles_per_page
));

我从数据库返回如下:

Array
(
[0] => Array
    (
        [Article] => Array
            (
                [id] => 1
            )

        [Tag] => Array
            (
                [0] => Array
                    (
                        [id] => 1
                        [name] => Ruby
                        [slug] => ruby
                        [uses] => 1
                        [ArticlesTag] => Array
                            (
                                [id] => 1
                                [article_id] => 1
                                [tag_id] => 1
                            )

                    )

            )

    )

如果我只想退回带有Ruby标签的文章怎么办?

【问题讨论】:

【参考方案1】:

试试这个

// In your Article model
function getArticleByTagSql($tag)
       
        $dbo = $this->getDataSource();
        $subQuery = $dbo->buildStatement(
        array(
                    'fields' => array('DISTINCT(ArticlesTag.article_id)'),
                    'table' => "articles_tags",                                    
                    'joins' => array(
                                array('table' => 'tags',
                                    'alias' => 'Tag',
                                    'type' => 'INNER',
                                    'conditions' => array('ArticlesTag.tag_id = Tag.id')
                                    )
                                ),
                    'alias'=>"ArticlesTag",                                         
                    'conditions' => array("Tag.name"=>Sanitize::clean($tag_words)),
                    'order' => null,
                    'group' => "ArticlesTag.article_id"
                    ),
                    $this
                    );
                    $subQuery = ' Article.id  IN (' . $subQuery . ')';
                    return $dbo->expression($subQuery);



// In your Articles Controller

$this->paginate['conditions'][] = $this->Article->getArticleByTagSql($tag_name);
$this->paginate['conditions'][] = array('Article.status' => 'active');
$this->paginate['limit'] = $this->articles_per_page;



// or as per your example
$articles = $this->Article->find('all', array(
                // extra condition to check for tag, maybe?
                'conditions'    => array('Article.status' => 'active',$this->Article->getArticleByTagSql($tag_name)), 
                'limit'         => $this->articles_per_page,
                'offset'        => ($page_num-1)*$this->articles_per_page
            ));

【讨论】:

【参考方案2】:

对于这样的情况,您可以使用LinkableBehavior。它专为您想要的结果而设计。如果你不想使用它,你必须在标签控制器上做一个查询:

$this->Tag->find('all', array('conditions' => array('Tag.name' => 'ruby')));

【讨论】:

是您在我的回答中留下的评论。我在分页中使用了类似的东西。但我无法验证,因为我无法访问我的蛋糕机。我回家后看看,谢谢提醒。 如果我从标签控制器执行查询,我会遇到几乎相同的问题。这是因为文章有一个状态字段,我需要检查状态是否处于活动状态。 @Paramount,所以 Leo 的解决方案是可行的方法【参考方案3】:

不可能直接。

最简单的方法是通过标签控制器进行查询

【讨论】:

【参考方案4】:

我正在用 Cakephp 3.x 的答案更新这个问题。

您可以使用 INNER JOIN 找到给定 tag 的所有 articles。这种连接的好处是它保持 articles 作为查询中的主表。当您通过 HABTM 连接对结果进行分页时,这是一个简单的解决方案。

$tag_id = 3; // the ID of the tag

$query = $this->Articles->find('all')
                 ->innerJoin('articles_tags', [
                      'Articles.id = articles_tags.article_id',
                      'articles_tags.tag_id' => $tag_id
                 ]);

第一个连接条件必须是数组键。如果您使用=> 数组赋值,那么CakePHP 会将articles_tags.article_id 作为字符串 参数传递给连接条件。这是行不通的。

您还可以为多个 HABTM 条件堆叠 innerJoin。例如;查找 tagcategory 的所有 articles。您还可以使用in 查询表达式来匹配多个标签

你也可以像$articles = $this->paginate($query);这样在分页中使用上面的内容

我确定此信息已在网络上发布,但此问题是谷歌搜索结果的首位。所以也许这会帮助其他人。

【讨论】:

以上是关于带有“hasAndBelongsToMany”的控制器的 CakePHP 条件查询的主要内容,如果未能解决你的问题,请参考以下文章

CakePHP模型hasAndBelongsToMany关联

在 hasAndBelongsToMany (HABTM) Cakephp 方面需要帮助

PHP CakePHP模型hasAndBelongsToMany关联

CakePHP hasAndBelongsToMany (HABTM) 删除加入记录

CakePHP hasAndBelongsToMany vs hasMany 通过

CakePHP 如何处理带有/不带有 'id' 字段的 HABTM 表?