CakePHP和HABTM模型限制错误

时间:2010-02-12 21:04:46

标签: php mysql cakephp

我有一系列Post模型,其中包含AndBelongsToMany Media模型。在Post模型内部的某些函数调用中,我不需要检索整个Media模型列表。但是,当我使用以下代码时:

$this->unbindModel( array('hasAndBelongsToMany' => array('Media')) );

// Rebind to get only the fields we need:
$this->bindModel(
        array('hasAndBelongsToMany' => array(
            'Media' => array(
                'className' => 'Media',
                'joinTable' => 'media_posts',
                'foreignKey' => 'post_id',
                'associationForeignKey' => 'media_id',
                'limit' => 1, 
                'fields' => array('Media.type', 'Media.path', 'Media.title')
            )
        )
    )
);
$this->find('all', $params);

此限制仅适用于第一个检索到的Post模型之一,并且所有后续Post模型都没有关联的媒体:

Array
(
    [0] => Array
        (
            [Profile] => Array
                (
                )

            [Media] => Array
                (
                    [0] => Array
                        (
                            [type] => photo
                            [path] => ''
                            [title] => ''
                        )

                )
        )

    [1] => Array
        (
            [Profile] => Array
                (
                )

            [Media] => Array
                (
                )

        )

)

任何建议都会很棒。谢谢!

4 个答案:

答案 0 :(得分:3)

为什么不使用containable behaviour

// you would probably want the next line in the app_model ot be able to use it with all models
$this->Post->actsAs = array('Containable')
$params['conditions'] = array(
);
$params['contain'] = array(
    'Media' => array(
        'fields' => array(
            'type', 'path', 'title'
        ),
        'limit' => 1
    )
);
$this->Post->find('all', $params);

编辑:

试过这个并得到了这个sql(Module< - > Tag):

SELECT `Module`.`id` FROM `modules` AS `Module` WHERE 1 = 1 

SELECT `Tag`.`id`, `ModulesTag`.`module_id`, `ModulesTag`.`tag_id` 
FROM `tags` AS `Tag` 
JOIN `modules_tags` AS `ModulesTag` 
  ON (`ModulesTag`.`module_id` IN (1, 2, 3, 4) AND `ModulesTag`.`tag_id` = `Tag`.`id`) 
WHERE `Tag`.`belongs_to` = 'Module' 
ORDER BY `Tag`.`name` ASC 
LIMIT 1

显然无法返回想要的结果,因为您必须对每个模块结果进行查询(这会再次导致查询过多)。

作为结论,我将返回所有标签(在我的示例中),因为太多结果行的开销优于太多查询的开销。

答案 1 :(得分:1)

Cake在一个批处理查询中获取所有与Habtm相关的记录,然后将它们组装到结果数组中。您在关联中指定的任何其他条件将在查询中使用,因此它看起来像这样:

SELECT … FROM Media WHERE Media.id in (1, 2, 3, …) LIMIT 1

所以它只会检索一个HABTM模型。

对此没有明显的解决方案。也许你可以再次考虑原始前提以及为什么“第一”(LIMIT 1)记录应该是正确的,也许你可以找到一个不同的条件来查询。

如果不这样做,您可以重新绑定模型,以便Media与hasMany {枢轴表}建立medias_posts关系。对于hasMany和belongsTo查询,Cake会自动执行JOIN个查询。您可以使用GROUP BY子句,这将为您提供所需的结果:

SELECT … FROM Media JOIN medias_posts … GROUP BY medias_posts.post_id

您可能还想尝试将'join'参数与查询一起传递,以实现该效果,而无需进行大量重新绑定。

$this->Media->find('all', array('join' => array(…), …));

答案 2 :(得分:0)

试试这个:

$this->yourModel->hasAndBelongsToMany['Media'] = false; // or null

然后手动设置您的HABTM关联

$this->yourModel->hasAndBelongsToMany['Media'] = array(........);

或者只是修改关联而不将其归零:

$this->yourModel->HABTM['Media']['fields'] = array(....)

答案 3 :(得分:0)

CakePHP为此containable behaviour

提供了一个非常强大的工具