使用ActiveRecord与Yii2logging实际的SQL查询?
我正在这样做:
$students = Student::find()->all(); return $this->render('process', array('students' => $students));
然后在这个视图中:
foreach($students as $student) { echo $student->name . ', '; echo $student->getQuizActivitiesCount(); ?> <br /> <?php }
我想看到正在执行的SQL查询。 一个学生“有很多”测验活动,查询执行完美,但我需要看到原始的SQL。 这可能吗?
方法1
使用返回yii\db\ActiveQuery
实例的关系,可以直接在代码中使用var_dump()
提取原始SQL查询。
例如,如果我们有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
这在我看来更简单了,我个人更喜欢这个debuggingSQL查询。
Yii 2内置了debugging模块。 只需将此添加到您的configuration:
'modules' => [ 'debug' => [ 'class' => 'yii\debug\Module', ], ],
确保你只有本地,而不是生产。 如果需要,还可以更改allowedIPs
属性。
这给你function面板在页面的底部。 findDB
字,然后点击数量或时间。 在此页面上,您可以查看所有执行的查询并对其进行过滤。 我通常不会在网格中对它们进行过滤,并使用标准的浏览器search快速浏览并find必要的查询(例如,使用表名作为关键字)。
方法3
只是在查询中出现错误,例如在列名称中,而不是city
。 这将导致数据库exception,然后您可以即时看到错误消息中生成的查询。
除了arogachev答案之外,当你已经使用了一个ActiveQuery
对象的时候,这里是我search查看rawsql的那一行。
/* @var $studentQuery ActiveQuery */ $studentQuery = Student::Find(); // Construct the query as you want it $studentQuery->where("status=3")->orderBy("grade ASC"); // Get the rawsql >-- The line I usually use --< var_dump(studentQuery->prepare(Yii::$app->db->queryBuilder)->createCommand()->rawSql); // Run the query $studentQuery->all();
你可以试试这个,假设你有一个查询给出像:
$query = new Books::find()->where('author=2'); echo $query->createCommand()->sql;
或者获取包含所有参数的SQL请尝试:
$query->createCommand()->getRawSql()
如果要在控制台应用程序中loggingActiveRecord
所有关系查询,所有build议的方法都无济于事。 它们只显示活动logging表中的主要SQL, \yii\debug\Module
仅在浏览器中工作。
获取所有执行的SQL查询的替代方法是通过添加指定的FileTarget来configuration它们来logging它们:
'log' => [ 'targets' => [[ ... ], [ 'class' => 'yii\log\FileTarget', 'logFile' => '@runtime/logs/profile.log', 'logVars' => [], 'levels' => ['profile'], 'categories' => ['yii\db\Command::query'], 'prefix' => function($message) { return ''; } ]] ]
UPDATE
为了logging插入/更新/删除查询,还应该添加yii\db\Command::execute
类别:
'categories' => ['yii\db\Command::query', 'yii\db\Command::execute']
当你有一个查询对象,你也可以使用
$query->createCommand()->getRawSql()
返回包含参数的原始SQL
$query->createCommand()->sql
这将分别输出参数的Sql。
为了logging/跟踪每个/ 所有查询:
扩展\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; } }
然后,简单地改变你的数据库连接在你的数据库configuration如下所示:
'db' => [ 'class' => 'app\base\Connection', // #### HERE 'dsn' => 'pgsql:host=localhost;dbname=dbname', 'username' => 'uname', 'password' => 'pwd', 'charset' => 'utf8', ],
现在,你可以跟踪/读取/ …由db
连接执行的所有查询。
试试像,
$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)