使用ActiveRecord和Yii2记录实际的SQL查询?

时间:2014-12-09 21:27:36

标签: php sql activerecord logging yii2

我这样做:

$students = Student::find()->all();
    return $this->render('process', array('students' => $students));

然后在视图中显示:

foreach($students as $student)
    {
        echo $student->name . ',  ';
        echo $student->getQuizActivitiesCount(); ?> <br /> <?php
    }

我想看看正在执行的sql查询。一个学生&#34;有很多&#34;测验活动,查询表现完美,但我需要看原始SQL。这有可能吗?

7 个答案:

答案 0 :(得分:69)

方法1

如果关系返回yii\db\ActiveQuery个实例,则可以直接在代码中提取原始SQL查询,例如使用var_dump()

例如,如果我们有user关系:

/**
 * @return \yii\db\ActiveQuery
 */
public function getUser()
{
    return $this->hasOne(User::className(), ['id' => 'user_id']);
}

然后你可以像var_dump()那样使用原始SQL:

var_dump($model->getUser()->prepare(Yii::$app->db->queryBuilder)->createCommand()->rawSql);
exit();

请注意,您应该像这样调用它而不是$model->user->...(后者返回User实例)。

但在您的情况下,由于count()立即返回int,因此无法实现。您可以var_dump()部分查询而不count(),但我认为这不方便。

请注意,您可以使用此方法转储任何ActiveQuery实例的生成SQL(不仅仅是关系返回的实例),例如:

$query = User::find()->where(['status' => User::STATUS_ACTIVE]);
var_dump($query->prepare(Yii::$app->db->queryBuilder)->createCommand()->rawSql);
exit();

方法2

在我看来,这个更简单,我个人更喜欢在调试SQL查询时使用这个。

Yii 2内置调试模块。只需将其添加到您的配置中:

'modules' => [
    'debug' => [
        'class' => 'yii\debug\Module',
    ],
],

确保您只在本地使用,而不是在生产中。如果需要,还可以更改allowedIPs属性。

这为您提供了页面底部的功能面板。找到DB字词,然后点击计数或时间。在此页面上,您可以查看所有已执行的查询并过滤它们。 我通常不会在网格中过滤它们并使用标准浏览器搜索来快速浏览并找到必要的查询(例如,使用表名作为关键字)。

方法3

只是在查询中出错,例如在列名中 - cityy而不是city。这将导致数据库异常,然后您可以立即在错误消息中看到生成的查询。

答案 1 :(得分:17)

你可以试试这个,假设你有一个如下的查询:

$query = new Books::find()->where('author=2');
echo $query->createCommand()->sql;

或者获取包含所有参数的SQL,请尝试:

$query->createCommand()->getRawSql()

答案 2 :(得分:17)

如果要在控制台应用程序中记录ActiveRecord的所有关系查询,则所有提议的方法都无济于事。它们仅显示活动记录表上的主要SQL,\yii\debug\Module仅适用于浏览器。

获取所有已执行SQL查询的替代方法是通过向配置添加特定FileTarget来记录它们:

'log' => [
    'targets' => [[
        ...
    ], [
        'class' => 'yii\log\FileTarget',
        'logFile' => '@runtime/logs/profile.log',
        'logVars' => [],
        'levels' => ['profile'],
        'categories' => ['yii\db\Command::query'],
        'prefix' => function($message) {
            return '';
        }
    ]]
]

<强>更新

为了记录插入/更新/删除查询,还应添加yii\db\Command::execute类别:

'categories' => ['yii\db\Command::query', 'yii\db\Command::execute']

答案 3 :(得分:16)

除了arogachev的回答,当你已经使用ActiveQuery对象时,这里是我搜索查看rawsql的行。

/* @var $studentQuery ActiveQuery */
$studentQuery = Student::Find();
// Construct the query as you want it
$studentQuery->where("status=3")->orderBy("grade ASC");

// Get the rawsql
var_dump($studentQuery->prepare(Yii::$app->db->queryBuilder)->createCommand()->rawSql);

// Run the query
$studentQuery->all();

答案 4 :(得分:6)

如果您有查询对象,也可以使用

from django.contrib import admin
from .models import File, Post, UserProfile

admin.site.register(File)
admin.site.register(Post)
admin.site.register(UserProfile)

返回包含参数的原始SQL或

$query->createCommand()->getRawSql()

将分别输出带参数的Sql。

答案 5 :(得分:5)

要记录/跟踪每个/ 所有查询:

扩展\yii\db\Connection并覆盖createCommand方法,如下所示:

namespace app\base;

class Connection extends \yii\db\Connection {

    public function createCommand($sql = null, $params = array()) {
        $createCommand = parent::createCommand($sql, $params);
        $rawSql = $createCommand->getRawSql();
         // ########### $rawSql -> LOG IT / OR DO ANYTHING YOU WANT WITH IT
        return $createCommand;
    }
}

然后,只需在db配置中更改数据库连接,如下所示:

'db' => [
        'class' => 'app\base\Connection', //  #### HERE 
        'dsn' => 'pgsql:host=localhost;dbname=dbname',
        'username' => 'uname',
        'password' => 'pwd',
        'charset' => 'utf8',
    ],

现在,您可以跟踪/读取/ ... db连接执行的所有查询。

答案 6 :(得分:2)

尝试,

$query = Yii::$app->db->createCommand()
        ->update('table_name', ['title' => 'MyTitle'],['id' => '1']);

var_dump($query->getRawSql()); die();
$query->execute();

输出:

string 'UPDATE `table_name` 
        SET `title`='MyTitle' WHERE `id`='1'
' (length=204)