Подтвердить что ты не робот

Запрашивать фактический 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. возможно ли это?

4b9b3361

Ответ 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)