2012-05-17 10 views
10

ho il seguente codice per ottenere alcuni record da dbYii - Come stampare SQL utilizzata da findAll

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

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

E 'possibile ottenere il codice SQL che viene utilizzato dal findAll? So che puoi ottenerlo dalla console di debug. Ma sto eseguendo lo script in background usando yiic.php

risposta

16

È possibile registrare le query eseguite nel registro dell'applicazione ed esaminarle. Qualcosa di simile nel file di configurazione:

'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', 
    ), 
    ), 
), 
); 

In alcuni casi (ad esempio durante l'esecuzione di test), sarà anche necessario chiamare Yii::app()->log->processLogs(null); al termine del processo per questo al lavoro.

Ovviamente, una volta che ci sei, niente ti impedisce di scrivere la tua rotta di log che fa qualcosa di diverso con i messaggi registrati, ma ricorda che i log vengono elaborati alla fine della richiesta (o quando chiami processLogs) , non ogni volta che si registra qualcosa.


A proposito, non è necessario creare query del genere, con input dinamico direttamente nella query. variabili Uso bind invece:

$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); 
+0

non sembra DAO con comando sql diretto è molto più semplice/più veloce rispetto all'utilizzo di CDbcriteria? – itachi

+3

Dipende da cosa si vuole fare con il risultato, suppongo. Se si desidera utilizzare la funzionalità del modello (ad esempio la convalida), l'utilizzo di AR è una scelta ovvia. Personalmente, preferisco AR e lascia DAO solo per situazioni più complesse come l'aggiornamento che coinvolge un join. In questo modo posso utilizzare gli ambiti del modello per condizioni comuni e non dover rivedere/aggiornare manualmente tutti i comandi diretti quando lo schema o la logica aziendale cambia. (Inoltre, usare AR ovunque significa un modo coerente per accedere ai dati contenuti nei risultati, senza doversi preoccupare se la riga del risultato è un oggetto o un array ...) – DCoder

+0

ha ottenuto il tuo punto. Grazie per la spiegazione. – itachi

1

Si può vedere accedere direttamente sulla tua pagina:

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

si può ottenere SQL utilizzando CDbCommandBuilder, in questo modo:

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

+1

Questa è una buona soluzione per le query semplici, ma non [considera "con"] (https://github.com/yiisoft/yii/blob/1.1.1/framework/db/schema/CDbCommandBuilder.php#L74) che è stato indicato nell'esempio OP – Motin

0

Se non voglio eseguire la query prima di vedere l'SQL, questo non è in realtà facile come potresti sperare.

È sporco come sbagliato ma, quando è solo in fase di sviluppo, in passato ho preso in considerazione l'aggiunta di un errore deliberato nei criteri e l'affidamento all'eccezione risultante per dare il tentativo SQL.

ad es.

$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); 

ho trovato il metodo di Ilya ad essere inaffidabile (non so perché, ma a volte il criterio viene ignorato utilizzando questo metodo).

5
  • Primo modo (via ufficiale):
    Nel file di configurazione main.php aggiungere questi due parametri nel vostro log section e si possono vedere i messaggi di log alla fine della pagina o FireBug Console nel browser. non dimenticare di impostare i parametri necessari nella sezione 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, ), ), ), );

  • Secondo modo:
    Nel codice basta cambiare l'ortografia di una delle colonne a qualcosa di errato e si otterrà un messaggio di errore contiene query full SQL nella vostra pagina di errore (si dovrebbe essere nella modalità YII_DEBUG true).qualcosa di simile:
    (ho cambiato t.date-t.wrong_date, quando si aggiorna la pagina, si vedrà il codice SQL generato che è stato eseguito nel database)

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

in entrambi i modi, avere YII_DEBUG true in index.php

defined('YII_DEBUG') or define('YII_DEBUG',true); 
+1

Uso sempre il secondo – Xcoder