Запрашивать фактический SQL-запрос с помощью ActiveRecord с 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. у ученика "есть много" викторинов, и запрос выполняется отлично, но мне нужно увидеть исходный SQL. возможно ли это?
Ответы
Ответ 1
Метод 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()
, но я думаю, что это не удобно.
Обратите внимание, что вы можете использовать этот метод для сброса сгенерированного SQL любых экземпляров ActiveQuery
(а не только те, которые были возвращены отношением), например:
$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
и нажмите либо счет, либо время. На этой странице вы можете просмотреть все выполненные запросы и отфильтровать их.
Обычно я не фильтрую их в Grid и использую стандартный поиск в браузере, чтобы быстро перемещаться и находить нужный запрос (например, используя имя таблицы как ключевое слово).
Метод 3
Просто сделайте ошибку в запросе, например, в имени столбца - cityy
вместо city
. Это приведет к ошибке базы данных, а затем вы сможете мгновенно увидеть сгенерированный запрос в сообщении об ошибке.
Ответ 2
вы можете попробовать это, предположим, что у вас есть запрос:
$query = new Books::find()->where('author=2');
echo $query->createCommand()->sql;
или чтобы получить SQL со всеми включенными параметрами try:
$query->createCommand()->getRawSql()
Ответ 3
Если вы хотите регистрировать все реляционные запросы 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 '';
}
]]
]
UPDATE
Чтобы записывать запросы вставки/обновления/удаления, нужно также добавить yii\db\Command::execute
категорию:
'categories' => ['yii\db\Command::query', 'yii\db\Command::execute']
Ответ 4
В дополнение к ответу арогачева, когда вы уже работаете с объектом 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();
Ответ 5
когда у вас есть объект запроса, вы также можете использовать
$query->createCommand()->getRawSql()
чтобы вернуть исходный SQL с включенными параметрами или
$query->createCommand()->sql
который будет выводить Sql с параметрами отдельно.
Ответ 6
Чтобы записывать/отслеживать все / все запросы:
expand \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, как показано ниже:
'db' => [
'class' => 'app\base\Connection', // #### HERE
'dsn' => 'pgsql:host=localhost;dbname=dbname',
'username' => 'uname',
'password' => 'pwd',
'charset' => 'utf8',
],
Теперь вы можете отслеживать/читать/... все запросы, выполняемые соединением db
.
Ответ 7
Попробуйте,
$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)