web-dev-qa-db-ja.com

Yii2でActiveRecordを使用して実際のSQLクエリを記録しますか?

私はこれをやっています:

$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を確認する必要があります。これは可能ですか?

45
diabetesjones

方法1

yii\db\ActiveQueryインスタンスを返すリレーションでは、たとえばvar_dump()を使用して、コードで生のSQLクエリを直接抽出できます。

たとえば、user関係がある場合:

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

次に、そのような生のSQLをvar_dump()できます:

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

$model->user->...ではなく、そのように呼び出す必要があることに注意してください(後者はUserインスタンスを返します)。

ただし、count()はすぐにintを返すため、これは不可能です。 var_dump()なしでcount()部分クエリを実行できますが、便利ではないと思います。

このメソッドは、リレーションによって返されたものだけでなく、ActiveQueryインスタンスの生成されたSQLをダンプするために使用できることに注意してください。例:

$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 Wordを見つけて、カウントまたは時間をクリックします。このページでは、実行されたすべてのクエリを表示し、それらをフィルタリングできます。私は通常、グリッドでそれらをフィルタリングせず、標準のブラウザ検索を使用して、必要なクエリをすばやくナビゲートして見つけます(たとえば、テーブル名をキーワードとして使用)。

方法

たとえば、列名-cityyの代わりにcityなどのクエリでエラーを作成します。これはデータベース例外として発生し、生成されたクエリを即座にエラーメッセージで確認できます。

70
arogachev

コンソールアプリケーションで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']
17
Ezze

これを試すことができます。次のようなクエリがあると仮定します。

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

または、すべてのパラメーターを含むSQLを取得するには、次を試してください。

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

Arogachevの答えに加えて、すでに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();
16
Mat

クエリオブジェクトがある場合は、使用することもできます

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

パラメータが含まれるRaw SQLを返すか、

$query->createCommand()->sql

パラメータ付きのSqlを個別に出力します。

6
ChrisB

Every/allクエリを記録/追跡するには:

以下のように\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 configでdb接続を変更します。

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

これで、db接続によって実行されたすべてのクエリを追跡/読み取り/ ...できるようになりました。

5

のように試してください、

$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)
2
Adil Abbasi