web-dev-qa-db-fra.com

Yii - Comment imprimer le code SQL utilisé par findAll

J'ai le code suivant pour obtenir des enregistrements de db

    $criteria = new CDbCriteria();
    $criteria->condition = 't.date BETWEEN "'.$from_date.'" AND "'.$to_date.'"';
    $criteria->with = array('order');

    $orders = ProductOrder::model()->findAll($criteria);

Est-il possible d'obtenir le code SQL utilisé par findAll? Je sais que vous pouvez l'obtenir à partir de la console de débogage. Mais je lance le script en arrière-plan avec yiic.php

12
Adrian Gunawan

Vous pouvez consigner les requêtes exécutées dans le journal d'application et les consulter. Quelque chose comme ça dans le fichier de configuration:

'components' => array(
  'db'=>array(
    'enableParamLogging' => true,
  ),
  'log'=>array(
    'class'=>'CLogRouter',
    'routes'=>array( 
      array(
        'class'=>'CFileLogRoute',
        'levels'=>'trace,log',
        'categories' => 'system.db.CDbCommand',
        'logFile' => 'db.log',
      ), 
    ),
  ),
);

Dans certains cas (par exemple lors de l'exécution de tests), vous devrez également appeler Yii::app()->log->processLogs(null); à la fin du processus pour que cela fonctionne.

Bien sûr, une fois que vous y êtes, rien ne vous empêche d'écrire votre propre itinéraire de journalisation qui fait les choses différemment avec les messages journalisés, mais n'oubliez pas que les journaux sont traités à la fin de la demande (ou lorsque vous appelez processLogs), pas à chaque fois. vous enregistrez quelque chose.


À propos, vous ne devriez pas construire de telles requêtes, avec une entrée dynamique directement dans la requête. Utilisez plutôt des variables liées:

$criteria = new CDbCriteria();
$criteria->condition = 't.date BETWEEN :from_date AND :to_date';
$criteria->params = array(
  ':from_date' => $from_date,
  ':to_date' => $to_date,
);
$criteria->with = array('order');

$orders = ProductOrder::model()->findAll($criteria);
16
DCoder
  • Première voie (voie officielle):  
    Dans votre fichier de configuration main.php, ajoutez ces deux paramètres à votre log section et vous pourrez voir les messages du journal à la fin de votre page ou FireBug Console dans votre navigateur. n'oubliez pas de définir les paramètres nécessaires dans la section db.

    'components' => array( 'db'=>array( 'enableProfiling'=>true, 'enableParamLogging' => true, ), 'log'=>array( 'class'=>'CLogRouter', 'routes'=>array( array( 'class'=>'CWebLogRoute', 'showInFireBug' => true, ), array( 'class'=>'CProfileLogRoute', 'levels'=>'profile', 'enabled'=>true, ), ), ), );

  • Deuxième voie:  
    Dans votre code, remplacez l’orthographe de l’une de vos colonnes par un signe incorrect et vous obtiendrez un message d’erreur contenant une requête SQL complète dans votre page d’erreur (vous devriez être en mode YII_DEBUG en mode true). quelque chose comme ça: 
    (J'ai changé t.date en t.wrong_date, lorsque vous actualiserez votre page, vous verrez le code SQL généré qui a été exécuté dans votre base de données)

$criteria = new CDbCriteria(); $criteria->condition = 't.wrong_date BETWEEN "'.$from_date.'" AND "'.$to_date.'"'; $criteria->with = array('order'); $orders = ProductOrder::model()->findAll($criteria);

dans les deux cas, YII_DEBUG true dans index.php

defined('YII_DEBUG') or define('YII_DEBUG',true);
6
Mohammad Eghlima

Vous pouvez obtenir SQL en utilisant CDbCommandBuilder, comme ceci:

ModelClassName::model()-> getCommandBuilder()-> createFindCommand('tableName', $criteria)->text;

4
Ilya Malyutin

Si vous ne souhaitez pas exécuter la requête avant d'afficher le code SQL, ce n'est pas aussi simple que vous le souhaiteriez. 

C'est aussi sale que mal, mais, une fois en développement seulement, j’ai pris le parti d’ajouter délibérément une erreur délibérée dans les critères et de me fier à l’exception résultante pour donner le code SQL tenté.

par exemple.

$criteria = new CDbCriteria();
$criteria->condition = 't.date_fgjhfgjfgj BETWEEN :from_date AND :to_date';
$criteria->params = array(
  ':from_date' => $from_date,
  ':to_date' => $to_date,
);
$criteria->with = array('order');
$orders = ProductOrder::model()->findAll($criteria);

J'ai trouvé que la méthode d'Ilya n'était pas fiable (je ne sais pas pourquoi, mais parfois, les critères sont ignorés avec cette méthode).

1
Arth

Vous pouvez voir log directement sur votre page:

'log'=>array(
    'class'=>'CLogRouter',
    'routes'=>array(
        array(
            'class'=>'CWebLogRoute',
        ),
    ),
),
1
gSorry