【问题标题】:CakePHP 1.3 contain not building associations correctlyCakePHP 1.3 包含未正确构建关联
【发布时间】:2013-03-22 20:34:04
【问题描述】:

这是我在这里的第一个问题。我在 cakephp 1.3 中遇到了可包含行为的问题。问题如下:我有一个具有以下关联的可交付模型:

class Deliverable extends AppModel {
  var $name = 'Deliverable';
  var $displayField = 'name';
  var $actsAs = array('Containable');

  var $belongsTo = array(
    'Asset' => array(
        'className' => 'Asset',
        'foreignKey' => 'asset_id',
        'dependent' => false
    ),
    'DelRouteName' => array(
        'className' => 'DelRouteName',
        'foreignKey' => 'del_route_name_id',
    ),
    'AccessGroup' => array(
        'className' => 'AccessGroup',
        'foreignKey' => false,
        'conditions' =>
            'Deliverable.role_id = AccessGroup.id'
    )
);

  var $hasOne = array(
    'Artifact' => array(
        'className' => 'Artifact',
        'foreignKey' => 'deliverable_id',
        'dependent' => true,
    )
);

  var $hasMany = array(
    'Delivery' => array(
        'className' => 'Delivery',
        'foreignKey' => 'deliverable_id',
        'dependent' => true,
        'order' => 'Delivery.gmt_created',
    )
);

这里是分页设置的配置:

$this->paginate['Deliverable'] = array_merge($this->paginate['Deliverable'], array(
        'limit' => $this->getSysPref('items_per_page', 20),
        'conditions' => array(
            'Deliverable.role_id' => $this->myRoleSetIds(),
            'Deliverable.asset_id' => $asset['Asset']['id'],
            'Delivery.gmt_created >' => $keep_time
        ),
        'order' => 'Deliverable.name',
        'contain' => array(
            'AccessGroup',
            'Delivery' => array(
                'conditions' => array(
                    'Delivery.gmt_created >' => $keep_time
                ),
                'limit' => 1,
                'order' => 'Delivery.gmt_created DESC'                      
            ),
            'DelRouteName'
        )
    ));
    $deliverables = $this->paginate('Deliverable');

如您所见,附加了可包含的行为、定义的关联以及包含的关联模型(在分页配置部分中)。

我遇到的这个问题是它能够成功查询包含的模型“AccessGroup”和“DelRouteName”,但它没有获取关联的“Delivery”数据。只有当我在父模型(Deliverable)上设置针对子模型(Delivery)的条件时,才会出现该错误,这是我之前做过的并且完全合法的。我收到此 SQL 错误,您可以看到表交付根本没有加入,但 access_groups 和 del_route_names 是。

这是 cake 构建的 SQL:

SELECT "Deliverable"."id" AS "Deliverable__id", "Deliverable"."name" AS 
"Deliverable__name", "Deliverable"."artifact_name" AS "Deliverable__artifact_name", 
"Deliverable"."type" AS "Deliverable__type", "Deliverable"."asset_id" AS 
"Deliverable__asset_id", "Deliverable"."del_route_name_id" AS 
"Deliverable__del_route_name_id", "Deliverable"."artifact_id" AS 
"Deliverable__artifact_id", "Deliverable"."status" AS "Deliverable__status", 
"Deliverable"."delivery_id" AS "Deliverable__delivery_id",                         
"Deliverable"."deliverable_id" 
AS "Deliverable__deliverable_id", "Deliverable"."gmt_created" AS 
"Deliverable__gmt_created", "Deliverable"."locked" AS "Deliverable__locked", 
"Deliverable"."frozen" AS "Deliverable__frozen", "Deliverable"."cloaked" AS 
"Deliverable__cloaked", "Deliverable"."role_id" AS "Deliverable__role_id", 
"DelRouteName"."id" AS "DelRouteName__id", "DelRouteName"."name" AS                     
"DelRouteName__name", 
"DelRouteName"."type" AS "DelRouteName__type", "AccessGroup"."id" AS "AccessGroup__id", 
"AccessGroup"."name" AS "AccessGroup__name", "AccessGroup"."dn" AS "AccessGroup__dn", 
"AccessGroup"."filters" AS "AccessGroup__filters", "AccessGroup"."paths" AS 
"AccessGroup__paths" FROM "deliverables" AS "Deliverable" LEFT JOIN "del_route_names" 
AS "DelRouteName" ON ("Deliverable"."del_route_name_id" = "DelRouteName"."id") LEFT     
JOIN "access_groups" AS "AccessGroup" ON ("Deliverable"."role_id" = "AccessGroup"."id")      
WHERE "Deliverable"."role_id" = ('0') AND "Deliverable"."asset_id" = '2' AND 
"Delivery"."gmt_created" > '1361391936'   ORDER BY "Deliverable"."name" ASC  LIMIT 50 

这给了我这个错误(使用 postgresql)

Warning (2): pg_query() [http://php.net/function.pg-query]: Query failed: ERROR:  missing FROM-clause entry for table "Delivery"

我在这里不知所措,因此将不胜感激。如果您还需要更多信息,请告诉我。

【问题讨论】:

  • 使用 psql 命令行我添加了子句 LEFT JOIN "deliveries" as "Delivery" ON ("Delivery"."deliverable_id" = "Deliverable.id) WHERE "Delivery"."gmt_created" > 1 并且查询有效。 (我只是用了一个例子)

标签: php cakephp models containable


【解决方案1】:

您不能根据主模型调整包含的模型。 CakePHP 在执行contain() 时对每个模型使用单独的查询。如果您需要添加跨模型的条件,则需要使用JOINs

【讨论】:

  • 我很好奇,因为这不是我学到的。 cake 构建查询的方式允许您在主模型上提供以子模型为目标的条件,只要它们被包含。在这里,我正在对一个针对子(连接表)模型的 HABTM 进行分页,但附加到父模型......这非常好:
  • $this->paginate['Asset'] = array_merge($this->paginate['Asset'], array( 'conditions' => array( 'Asset.role_id' => $this->myRoleSetIds(), 'ProductsAsset.product_id' => $id ), 'contain' => array( 'ProductsAsset', 'AccessGroup' ) )); $assets = $this->paginate('Asset');
  • 以上代码完美运行,根据子模型的product_id过滤主模型。
  • 但是,您修复确实有效...我很好奇为什么跨模型条件“有时”有效,但在其他情况下无效(如本例)。
  • 另外一件事,如果你说的是真的,为什么当我在主模型上提供针对“AccessGroup”模型的条件时,查询运行良好?例如:'conditions' => array( 'Deliverable.role_id' => $this->myRoleSetIds(), 'Deliverable.asset_id' => $asset['Asset']['id'], 'AccessGroup.name' => 'This is a test', 'Delivery.gmt_created >' => $keep_time ); 我没有为 AccessGroup 包含“加入”,但条件已应用于主模型....
【解决方案2】:

在 Dave 的帮助下,更新后的代码现在可以运行了。

$this->paginate['Deliverable'] = array_merge($this->paginate['Deliverable'], array(
            'limit' => $this->getSysPref('items_per_page', 20),
            'conditions' => array(
                'Deliverable.role_id' => $this->myRoleSetIds(),
                'Deliverable.asset_id' => $asset['Asset']['id'],
                'Delivery.gmt_created >' => $keep_time
            ),
            'joins' => array(
                array(
                    'table' => 'deliveries',
                    'alias' => 'Delivery',
                    'type' => 'LEFT',
                    'conditions' => array(
                        'Deliverable.id = Delivery.deliverable_id'
                    )
                )
            ),
            'order' => 'Deliverable.name',
            'contain' => array(
                'AccessGroup',
                'Delivery' => array(
                    'conditions' => array(
                        'Delivery.gmt_created >' => $keep_time
                    ),
                    'limit' => 1,
                    'order' => 'Delivery.gmt_created DESC'                      
                ),
                'DelRouteName'
            )
        ));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多