【问题标题】:A CakePHP query calls COUNT() twice for no apparent reason一个 CakePHP 查询无缘无故地调用 COUNT() 两次
【发布时间】:2012-06-21 00:16:10
【问题描述】:

注意:我最初在一小时前提出了这个问题,但直到最近才意识到我犯了一个重大的复制和粘贴错误。一个如此重要,以至于删除旧帖子并重新开始更容易。对此感到抱歉。

在 CakePHP 框架中,在我更新了一个模型后,我转储了 SQL 查询。 COUNT(*) 被调用了两次,原因不明。

所以我有两个模型,$Foo$Bar。为简单起见,我没有定义它们之间的任何$belongsTo$hasMany 关系。问题只涉及 $Foo,但以防万一我也包含了 $Bar 的代码。

$data = array(
    'something' => 12,
    'something_else' => $this->Bar->field('id', $conditions),
);

$this->Foo->id = $this->Foo->field($data);
$this->Foo->save($data);

我根据一组条件(此处不相关)获取$Bar.id 字段。我使用该 id 来确定应该插入或更新到 $Foo$data。如果$Foo 的id 满足$data 的要求,则返回该值;如果不是 false 将被返回。根据 CakePHP 的架构,save() 将更新如果有一个有效的 id;否则它将插入。我很确定我没有做任何不寻常的事情。

这是我在 SQL 转储中看到的:

SELECT `Foo`.`id` FROM `foos` AS `Foo` WHERE `something` = 12 AND `something_else` = 1 LIMIT 1
SELECT COUNT(*) AS `count` FROM `foos` AS `Foo` WHERE `Foo`.`id` = 1
SELECT COUNT(*) AS `count` FROM `foos` AS `Foo` WHERE `Foo`.`id` = 1
UPDATE `foos` SET `something` = 12, something_else` = 1 WHERE `foos`.`id` = 1'

对于我的生活,我完全不知道为什么需要COUNT(),更不用说为什么它被调用了两次。有谁知道发生了什么?感谢您的帮助。

【问题讨论】:

    标签: php mysql cakephp cakephp-model


    【解决方案1】:

    我没有使用过CakePHP,但是查看源代码here,您会在字段函数中看到它调用了find 方法。

    因此,这个调用

    $data = array(
        'something' => 12,
        'something_else' => $this->Bar->field('id', $conditions),
    );
    

    生成:

    SELECT `Foo`.`id` FROM `foos` AS `Foo` WHERE `something` = 12 AND `something_else` = 1     LIMIT 1
    

    然后设置字段调用

    $this->Foo->id = $this->Foo->field($data);
    

    通过内部的 find 函数调用生成这个:

    SELECT COUNT(*) AS `count` FROM `foos` AS `Foo` WHERE `Foo`.`id` = 1
    

    Save函数在保存前也调用find查看记录是否存在,从而产生第二次调用:

    SELECT COUNT(*) AS `count` FROM `foos` AS `Foo` WHERE `Foo`.`id` = 1
    

    最后的查询是明显的保存本身。

    请自行确认我的阅读是否正确,但这似乎是这样做的。

    【讨论】:

    • 我相信这是正确的答案。非常感谢瑞秋!
    • 所以...这只是 CakePHP 的故意行为吗?
    • Alvaro,在四年前发表这篇文章的时候,它看起来是故意的,尽管从那以后我就没有看过代码。可以选择修改行为,但这超出了我的专业范围。
    【解决方案2】:

    无法告诉您发生了什么(因为我认为没有足够的代码),但可以为您提供解决方法。

    使用“INSERT INTO table(id, field, field2) VALUES(id, value, value2) ON DUPLICATE KEY UPDATE field=value, field2=value2" 语法进行查询。

    这使 SQL 可以检查重复项,并且还将消除检查行存在和尝试插入之间的那几分之一秒(以防在检查后另一个进程插入)。为此,“id”字段必须是主键或“唯一”索引,以便它知道触发更新。

    【讨论】:

    • 我同意 Robbie,而且我已经知道解决方法。我只是想了解 CakePHP 的包装器是如何工作的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    • 2012-11-19
    • 2016-02-04
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    相关资源
    最近更新 更多