【问题标题】:CakePHP not joining the correct tables in find queryCakePHP 没有在查找查询中加入正确的表
【发布时间】:2013-10-03 09:33:45
【问题描述】:

好的,我又问了一个蛋糕问题。

我有一个相当复杂的表结构,有很多连接。这是它的要点:

所以,总结一下:

RiskCategory $hasMany Client   [Client $belongsTo RiskCategory]
Client $hasMany Account        [Account $belongsTo Client]
Account $hasMany Holding       [Holding $belongsTo Account]

在我的RiskCategory 模型中,我想运行一个查询,该查询基本上返回每个 riskCategory id 中的持股总和,按日期分组。还有一些其他条件,但这是我总结的:

$findParams = array(
    'recursive' => 4,
    'fields' => array(
        'Holding.holding_date',
        'SUM(Holding.value) AS risk_category_value'
        ),
    'group' => array('Holding.holding_date'),
    'order' => 'Holding.holding_date ASC'
    );

$findParams['conditions'] = array(
    'Client.active' => true,
    'Client.model' => true,
    'Client.currency' => 'GBP',
    'OR' => array(
        'Holding.holding_date' => $this->end_date,
        array(
            'Holding.holding_date = LAST_DAY(Holding.holding_date)',
            'MONTH(Holding.holding_date)' => array(3,6,9,12)
            )
        )
    );

$valuations = $this->Client->Account->Holding->find( 'all', $findParams );

当我运行上面的蛋糕时,我给出了一个错误,说查询中不存在各种字段。创建的原始查询如下:

SELECT `Holding`.`holding_date`, 
       Sum(`Holding`.`value`) AS risk_category_value 
FROM   `ips_client_db`.`holdings` AS `Holding` 
       LEFT JOIN `ips_client_db`.`accounts` AS `Account` 
              ON ( `Holding`.`account_id` = `Account`.`id` ) 
       LEFT JOIN `ips_client_db`.`sedols` AS `Sedol` 
              ON ( `Holding`.`sedols_id` = `Sedol`.`id` ) 
WHERE  `client`.`active` = '1' 
       AND `client`.`model` = '1' 
       AND `client`.`currency` = 'GBP' 
       AND ( ( `Holding`.`holding_date` = '2013-10-01' ) 
              OR (( ( `Holding`.`holding_date` = Last_day( 
                      `Holding`.`holding_date`) ) 
                    AND ( Month(`Holding`.`holding_date`) IN ( 3, 6, 9, 12 ) ) ) 
                 ) ) 
GROUP  BY `Holding`.`holding_date` 
ORDER  BY `Holding`.`holding_date` ASC 

看起来 cake 没有完成所有的连接。它只是将Account 连接到Holding,然后将Holding 连接到Sedol(这是数据库中的另一个连接表,但此查询不需要,所以我在图中省略了它)

为什么没有正确连接以及如何实现?如果可能的话,我想避免写一个原始的声明。

编辑:连接应该如下:

...
FROM   risk_categories 
   LEFT JOIN ((clients 
               LEFT JOIN accounts 
                      ON clients.id = accounts.client_id) 
              LEFT JOIN holdings 
                     ON accounts.id = holdings.account_id) 
          ON risk_categories.id = clients.risk_category_id 
...

【问题讨论】:

  • 我认为 cake 不会在第一个查询中加入 clients。尝试将 account_idsedols_id 添加到字段列表中,看看是否有帮助,但 Cake 可能会添加客户端作为附加查询。
  • 不,我添加哪些字段没有区别,cake 会返回错误,除非这些字段在连接的表中
  • 如果您从条件中删除客户,Cake 是否会为客户返回记录?
  • 是的,我需要从条件和字段中删除Client,然后查询才能工作。
  • 好的,这是有道理的。我会为此发布答案。

标签: php mysql cakephp


【解决方案1】:

CakePHP 不会对深度超过 1 级的关联执行深度连接。这就是为什么在条件中引用 Client 表时出现错误的原因。

对于这些类型的问题,使用Containable 行为会更容易。我通常将此行为添加到我的AppModel 作为关联的默认处理程序。

Containable 允许您定义关联(仅那些已定义的关联)及其字段和条件,作为查找操作的一部分。这是通过在查找参数中添加一个新的contain 键来完成的。下面我猜测您可能需要什么。

$findParams = array(
    'fields' => array(
        'Holding.holding_date',
        'SUM(Holding.value) AS risk_category_value'
        ),
    'conditions'=>array(
        'OR' => array(
            'Holding.holding_date' => $this->end_date,
            array(
                'Holding.holding_date = LAST_DAY(Holding.holding_date)',
                'MONTH(Holding.holding_date)' => array(3,6,9,12)
                )
            )
    ),
    'group' => array('Holding.holding_date'),
    'order' => 'Holding.holding_date ASC',
    'contain'=>array(
        'Account'=>array(
           'Client'=>array(
                'RiskCategory',
                'conditions'=>array(
                    'Client.active' => true,
                    'Client.model' => true,
                    'Client.currency' => 'GBP',
                )
           )
        )
    )
);

$valuations = $this->Client->Account->Holding->find( 'all', $findParams );

【讨论】:

  • 我认为这可能与containable 有关,但按照您的建议,运行的查询与之前的查询相同。我删除了条件并在您的答案中使用了 contain 数组。此外,如果我决定包含像 Client.risk_category_id 这样的字段,我会得到与以前相同的错误。好像contain 数组被忽略了。
  • 您是否将public $actsAs = array('Containable'); 添加到您的AppModel 课程中?
  • 不,但我将它添加到我的 RiskCategory 类中,这是我从中运行查询的地方
  • @harryg 行为必须出现在查询中使用的所有模型中。这就是为什么我总是把它放在 AppModel 中。
  • 好的,它现在在AppModel 类中,但仍然没有区别
猜你喜欢
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 2017-02-05
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
相关资源
最近更新 更多