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

dia*_*nes 45 php sql logging activerecord yii2

我这样做:

$students = Student::find()->all();
    return $this->render('process', array('students' => $students));
Run Code Online (Sandbox Code Playgroud)

然后在视图中:

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

我想看看正在执行的SQL查询.学生"有很多"测验活动,查询表现完美,但我需要查看原始SQL.这可能吗?

aro*_*hev 70

方法1

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

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

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

然后您可以var_dump()像这样的原始SQL:

var_dump($model->getUser()->prepare(Yii::$app->db->queryBuilder)->createCommand()->rawSql);
exit();
Run Code Online (Sandbox Code Playgroud)

请注意,您应该这样调用它而不是$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();
Run Code Online (Sandbox Code Playgroud)

方法2

这在我看来简单得多,我个人更喜欢在调试SQL查询时这个.

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

'modules' => [
    'debug' => [
        'class' => 'yii\debug\Module',
    ],
],
Run Code Online (Sandbox Code Playgroud)

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

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

方法3

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


Sta*_*ser 17

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

$query = new Books::find()->where('author=2');
echo $query->createCommand()->sql;
Run Code Online (Sandbox Code Playgroud)

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

$query->createCommand()->getRawSql()
Run Code Online (Sandbox Code Playgroud)


Ezz*_*zze 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 '';
        }
    ]]
]
Run Code Online (Sandbox Code Playgroud)

UPDATE

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

'categories' => ['yii\db\Command::query', 'yii\db\Command::execute']
Run Code Online (Sandbox Code Playgroud)


Mat*_*Mat 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();
Run Code Online (Sandbox Code Playgroud)


Chr*_*isB 6

当你有一个查询对象时,你也可以使用

$query->createCommand()->getRawSql()
Run Code Online (Sandbox Code Playgroud)

使用包含的参数返回Raw SQL

$query->createCommand()->sql
Run Code Online (Sandbox Code Playgroud)

这将分别输出带参数的Sql.


Ali*_*our 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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