CakePHP在检索相关模型时运行不必要的查询

时间:2013-09-19 09:12:41

标签: cakephp cakephp-2.3

事件模型有以下关系:

var $belongsTo = array(
    'Project' => array(
        'className' => 'Project',
        'foreignKey' => 'project_id',

    ),
    'User' => array(
        'className' => 'User',
        'foreignKey' => 'user_id'
    )
    );

以下是我根据用户输入列出事件的方式:

$conditions = array('user_id'=>$id, 'date >=' => $from, 'date <=' => $to);
$events = $this->find('all', array(
                                'conditions'=>$conditions, 'order' => array('Event.date' => 'asc')));

以下是正在运行的3个查询:

1   SELECT `User`.`id`, `User`.`name`, `User`.`surname` FROM `scheduling`.`users` AS `User` WHERE `company_id` = 1

2   SELECT `Project`.`id`, `Project`.`name` FROM `scheduling`.`projects` AS `Project` LEFT JOIN `scheduling`.`customers` AS `Customer` ON (`Project`.`customer_id` = `Customer`.`id`) WHERE `Project`.`company_id` = 1

3   SELECT `Event`.`id`, `Event`.`project_id`, `Event`.`user_id`, `Event`.`date`, `Event`.`hours`, `Event`.`minutes`, `Event`.`xhours`, `Event`.`xminutes`, `Event`.`xdetails`, `Event`.`assignment`, `Event`.`start_time`, `Event`.`material`, `Event`.`meter_drive`, `Event`.`time_drive`, `Event`.`start_location`, `Event`.`finish_time`, `Project`.`id`, `Project`.`name`, `Project`.`customer_id`, `Project`.`project_nr`, `Project`.`address`, `Project`.`post_nr`, `Project`.`city`, `Project`.`company_id`, `Project`.`color`, `Project`.`start_date`, `Project`.`finish_date`, `User`.`id`, `User`.`employee_nr`, `User`.`name`, `User`.`surname`, `User`.`email`, `User`.`password`, `User`.`role`, `User`.`phone`, `User`.`address`, `User`.`post_nr`, `User`.`city`, `User`.`token_hash`, `User`.`company_id`, `User`.`car_id`, `User`.`image` FROM `scheduling`.`events` AS `Event` LEFT JOIN `scheduling`.`projects` AS `Project` ON (`Event`.`project_id` = `Project`.`id`) LEFT JOIN `scheduling`.`users` AS `User` ON (`Event`.`user_id` = `User`.`id`) WHERE `user_id` = 1 AND `project_id` = 5 AND `date` >= '2013-07-01' AND `date` <= '2013-12-06' ORDER BY `Event`.`date` asc

实际上,我只需要第三个查询而不是前两个查询。是什么导致他们以及如何摆脱他们?

4 个答案:

答案 0 :(得分:2)

默认情况下,CakePHP将尝试附加关联。

在所有3个模型中添加:

var $actsAs = array('Containable');

这样您就可以“查询”特定模型的查询。

现在你可以这样查询:

$events = $this->find('all', array(
                            'conditions'=>$conditions, 
                            'order' => array('Event.date' => 'asc'),
                            'contain' => true));

假设您确实想要用户(但不是项目),您可以这样做:

$events = $this->find('all', array(
                            'conditions'=>$conditions, 
                            'order' => array('Event.date' => 'asc'),
                            'contain' => array('User')));

答案 1 :(得分:1)

这会对你有帮助。

$events = $this->find('all', array(
    'conditions'=>$conditions, 
    'order' => array('Event.date' => 'asc'),
    'recursive' => -1
));

基于最大包含深度递归

答案 2 :(得分:1)

其他代码负责

此代码:

$conditions = array('user_id'=>$id, 'date >=' => $from, 'date <=' => $to);
$events = $this->find('all', array(
    'conditions'=>$conditions, 
    'order' => array('Event.date' => 'asc')
));

负责此查询:

SELECT 
    `Event`.`id`, 
    ...
FROM 
    `scheduling`.`events` AS `Event` 
LEFT JOIN 
    `scheduling`.`projects` AS `Project` ON (`Event`.`project_id` = `Project`.`id`) 
LEFT JOIN 
    `scheduling`.`users` AS `User` ON (`Event`.`user_id` = `User`.`id`) 
WHERE 
    `user_id` = 1 AND 
    `project_id` = 5 AND 
    `date` >= '2013-07-01' AND 
    `date` <= '2013-12-06' 
ORDER BY 
    `Event`.`date` asc

但问题代码中只有user_iddate条件。

这个条件:

`project_id` = 5

是由未显示的代码添加 - 可能是一种行为。检查代码中project_id条件的定义位置,有答案。

查询#1不相关

第一个查询根本看起来与问题中的代码无关 - 问题中没有任何内容需要查找用户的数据。要找到它的来源 - 你可以使用一种简单的技术。打开用户模型并将其放入其中:

class User extends AppModel {

    public function beforeFind() {
        debug(Debugger::trace());
        debug(func_get_args());
        die;
    }

}

这将给出如何触发查询的堆栈跟踪 - 一旦知道应用程序代码的来源,就可以适当地编辑它。

查询#2是必需的

假设您想要的查询实际上是正确的(查找单个项目的所有事件) - 需要有一种限制项目ID的方法。如果未明确指定,则第二个查询按客户端ID查找项目ID - 即您想要的查询取决于该数据。

答案 3 :(得分:0)

$conditions = array('user_id'=>$id, 'date >=' => $from, 'date <=' => $to);
$events = $this->find('all', array('recursive'=>0,
     'conditions'=>$conditions, 'order' => array('Event.date' => 'asc')));

这里的变化是递归

recursive =&gt; -1表示只获取事件

recursive =&gt; 0表示将获取它所属的事件+,在本例中为项目和用户