CakePHP:在执行前查看编译的SQL查询

17

每次运行我的查询都会出现超时错误。这是一个带有联接的分页查询。
我想调试SQL,但由于超时,我无法看到它。

在执行之前如何查看编译后的SQL查询语句?


一些蛋糕代码:

$this -> paginate = array(
        'limit' => '16',
        'joins' => array( array(
                'table' => 'products',
                'alias' => 'Product',
                'type' => 'LEFT',
                'conditions' => array('ProductModel.id = Product.product_model_id')
            )),
        'fields' => array(
            'COUNT(Product.product_model_id) as Counter',
            'ProductModel.name'
            ),
        'conditions' => array(
            'ProductModel.category_id' => $category_id,
        ),
        'group' => array('ProductModel.id')
    );
7个回答

31

首先,在app/config/config.php中将debug变量设置为2。

然后添加:

<?php echo $this->element('sql_dump');?>

在布局的末尾。这实际上应该在默认的 cake 布局中被注释掉。

现在,您将能够查看所有发送到数据库的 SQL 查询。

现在复制查询并在数据库上使用 SQL EXPLAIN 命令(链接适用于 MySQL)来查看查询在 DBMS 中的操作。有关 CakePHP 调试的更多信息,请查看此处

由于脚本甚至都没有渲染,因此您可以尝试直接从数据源获取最新的日志:

function getLastQuery()
{
    $dbo = $this->getDatasource();
    $logs = $dbo->getLog();
    $lastLog = end($logs['log']);
    return $lastLog['query'];
}

由于getDatasource()函数是在一个模型中定义的,所以这需要放在一个模型中。检查整个$logs变量并查看其中的内容。


谢谢。但是它没有起作用。 问题在于脚本从未到达渲染部分,因为超时在控制器操作级别。 - yossi
这个脚本会返回上一次执行的最后一个查询吗? - yossi
2
不确定因为我不记得确切的返回是什么。 试一下吧。它肯定会返回最后一个查询的日志。 只需转储“$logs”变量并检查它即可。 - Borislav Sabev
3
在控制器中调用时,请使用 ConnectionManager::getDataSource('default') 来获取数据源。 - Kangur

5

还有一件事情您可以做,那就是……

前往 Cake/Model/DataSource/DboSource.php 文件并找到 execute() 函数,然后打印 $sql 变量。这样就可以打印出 sql 语句。

这肯定不是最干净的方式(因为您正在更改 Cake 目录)……但如果某些东西与 sql 不起作用,这肯定是最快捷的调试方法。


当其他所有东西都因为一个恶意查询而彻底崩溃时,这有时是最有帮助的方法! - almcnicoll
2
答案对于没有访问“sql_dump”元素的命令行环境也很有帮助。 - Curtis Gibby
谢谢!这个帮了我 :) - olleh
1
受这个答案的启发,从Cakephp 3.9开始,分页器文件的路径是vendor/cakephp/cakephp/src/Datasource/Paginator.php,在其中可以在第172行打印$cleanQuery以快速查看查询。我尝试了几种其他方法,但它们都没有起作用。查询日志可以工作,但我想要它打印在页面上。 - Arvind K.

3

展示给定模型的所有执行查询的简单方法:

  $sqllog = $this->ModelName->getDataSource()->getLog(false, false);       
  debug($sqllog);

3
Try...
function getLastQuery($model) {
    $dbo = $model->getDatasource();
    $logData = $dbo->getLog();
    $getLog = end($logData['log']);
    echo $getLog['query'];
}

这个函数在安装了PHP 5.4.32的服务器上运行良好,但在安装了5.5.16版本的服务器上却无法正常工作,此时$dbo->getLog()为空。而在另一个服务器上,我可以得到完整的日志。有人知道为什么这个函数在5.5版本上不能正常工作吗? - user1555112
@user1555112 我不确定问题是什么,但在5.6.1上运行良好。 - Phillip Macdonald
@user1555112,可能你的配置文件中没有开启调试模式,如果你正在使用this->log或CakeLog。 - LogixMaster

2
class YourController extends AppController {
    function testfunc(){
        $this->Model->find('all', $options);
        echo 'SQL: '.$this->getLastQuery();
    }

    function getLastQuery()
    {
        $dbo = ConnectionManager::getDataSource('default');
        $logs = $dbo->getLog();
        $lastLog = end($logs['log']);
        return $lastLog['query'];
    }
}

或者你可以在 lib/Cake/Model/DataSource.php 中的 execute() 函数中添加以下行来获取所有的查询。
Debugger::dump($sql);

0

在app/config/config.php中将debug变量设置为2。

echo $this->Payment->save();

输出结果如 => SQL查询语句:INSERT INTO photoora_photoorange.payments VALUES (*******)

[插入查询][2]


-1

在app/config/config.php中将debug变量设置为2。

enter image description here

还有 在此输入图片描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接