web-dev-qa-db-fra.com

Consignez la requête SQL réelle en utilisant ActiveRecord avec Yii2?

Je fais ça:

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

et puis ceci dans la vue:

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

je voudrais voir la requête SQL en cours d'exécution. un étudiant "a de nombreuses" activités de quiz, et la requête fonctionne parfaitement, mais j'ai besoin de voir le SQL brut. Est-ce possible?

45
diabetesjones

Méthode 1

Avec les relations qui renvoient l'instance yii\db\ActiveQuery, Il est possible d'extraire la requête SQL brute directement dans le code, par exemple avec var_dump().

Par exemple, si nous avons user relation:

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

Vous pouvez alors var_dump() le SQL brut comme ceci:

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

Notez que vous devriez l'appeler comme ça et non pas $model->user->... (Ce dernier retourne User instance).

Mais dans votre cas, ce n'est pas possible car count() renvoie immédiatement int. Vous pouvez var_dump() requête partielle sans count(), mais je pense que ce n'est pas pratique.

Notez que vous pouvez utiliser cette méthode pour vider le SQL généré de n’importe quelle instance ActiveQuery (pas seulement celles qui ont été retournées par relation), par exemple:

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

Méthode 2

Ceci est beaucoup plus simple à mon avis et je préfère personnellement celui-ci lors du débogage de requêtes SQL.

Yii 2 a un module de débogage intégré. Ajoutez simplement ceci à votre config:

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

Assurez-vous de ne l'avoir que localement et non sur la production. Si nécessaire, changez également la propriété allowedIPs.

Cela vous donne un panneau fonctionnel au bas de la page. Trouvez le DB Word et cliquez sur le nombre ou le temps. Sur cette page, vous pouvez afficher toutes les requêtes exécutées et les filtrer. En général, je ne les filtre pas dans Grid et n'utilise que la recherche standard dans le navigateur pour naviguer rapidement et trouver la requête nécessaire (en utilisant le nom de la table comme mot clé, par exemple).

Méthode

Faites simplement une erreur dans la requête, par exemple dans le nom de la colonne - cityy au lieu de city. Cela entraînera une exception de base de données et vous pourrez alors voir instantanément la requête générée dans un message d'erreur.

70
arogachev

Si vous souhaitez consigner toutes les requêtes relationnelles de ActiveRecord dans une application console, toutes les méthodes proposées ne vous seront d'aucun secours. Ils ne montrent que le SQL principal sur la table de l'enregistrement actif, \yii\debug\Module ne fonctionne que dans le navigateur.

Une autre méthode pour obtenir toutes les requêtes SQL exécutées consiste à les consigner en ajoutant un FileTarget à la configuration:

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

[~ # ~] met à jour [~ # ~]

Pour consigner les requêtes d'insertion/mise à jour/suppression, vous devez également ajouter yii\db\Command::execute Catégorie:

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

vous pouvez essayer ceci, supposons que vous avez une requête donnée comme:

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

ou pour obtenir le code SQL avec tous les paramètres inclus, essayez:

$query->createCommand()->getRawSql()
17
Stack user

En plus de la réponse arogachev, lorsque vous travaillez déjà avec un objet ActiveQuery, voici la ligne que je cherche pour afficher le 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();
16
Mat

lorsque vous avez un objet de requête, vous pouvez également utiliser

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

renvoyer le SQL brut avec les paramètres inclus ou

$query->createCommand()->sql

qui produira le SQL avec les paramètres séparément.

6
ChrisB

Pour vous connecter/suivre toutes les/toutes requêtes:

étendre \yii\db\Connection et la méthode createCommand, comme ci-dessous:

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;
    }
}

Ensuite, changez simplement votre connexion à la base de données dans votre configuration de base de données comme ci-dessous:

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

Maintenant, vous pouvez suivre/lire/... toutes les requêtes exécutées par db connexion.

5
Ali MasudianPour

Essayez comme

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

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

Sortie:

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