Laravel 5でクエリを実行する方法は?空の配列を返すDB :: getQueryLog()


171

クエリのログを表示しようとしていますがDB::getQueryLog()、空の配列を返しています。

$user = User::find(5);
print_r(DB::getQueryLog());

結果

Array
(
)

このクエリのログを表示するにはどうすればよいですか?


Laravel Debugbarは、クエリをログに記録する優れたツールです。また、他にも多くの素晴らしい機能があります。
totymedli 2017年

回答:


256

Laravel 5ではデフォルトでクエリログが無効になっています。https//github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

次を呼び出して、クエリログを有効にする必要があります。

DB::enableQueryLog();

またはイベントリスナーを登録します:

DB::listen(
    function ($sql, $bindings, $time) {
        //  $sql - select * from `ncv_users` where `ncv_users`.`id` = ? limit 1
        //  $bindings - [5]
        //  $time(in milliseconds) - 0.38 
    }
);  

いくつかのヒント

1.複数のDB接続

複数のDB接続がある場合、ログに記録する接続を指定する必要があります

のクエリログを有効にするにはmy_connection

DB::connection('my_connection')->enableQueryLog();

のクエリログを取得するにはmy_connection

print_r(
   DB::connection('my_connection')->getQueryLog()
);

2.クエリログを有効にする場所

HTTPリクエストのライフサイクルでhandleは、一部のBeforeAnyDbQueryMiddleware ミドルウェアのメソッドでクエリログを有効にしてterminateから、同じミドルウェアのメソッドで実行されたクエリを取得できます。

class BeforeAnyDbQueryMiddleware
{
    public function handle($request, Closure $next)
    {
        DB::enableQueryLog();
        return $next($request);
    }

    public function terminate($request, $response)
    {
        // Store or dump the log data...
        dd(
            DB::getQueryLog()
        );
    }
}

ミドルウェアのチェーンは、artisanコマンドでは実行されないため、CLIの実行では、artisan.startイベントリスナーでクエリログを有効にできます。

たとえば、bootstrap/app.phpファイルに入れることができます

$app['events']->listen('artisan.start', function(){
    \DB::enableQueryLog();
});

3.メモリ

Laravelはすべてのクエリをメモリに保持します。そのため、多数の行を挿入する場合や、多数のクエリを使用して長時間実行ジョブを実行する場合など、場合によっては、アプリケーションが過剰なメモリを使用する可能性があります。

ほとんどの場合、クエリログはデバッグにのみ必要です。その場合は、開発にのみ有効にすることをお勧めします。

if (App::environment('local')) {
    // The environment is local
    DB::enableQueryLog();
}

参考文献


6
お使いのシステムに複数のDB接続を使用している場合は、それ以外の場合は空の配列を返すことがあります、それを指定する必要があります\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
ダイアナR.

コメントを回答@DianaRとして投稿してください。
Narendrasingh Sisodia 16年

1
Laravel 5.2については、laravel.com
Dmitri Chebotarev

Eloquent "NameController :: create();"をログに記録できるようにする方法 ステートメント?
ルベン・ルイス

2
Laravel 5.4では、DB::listenコールバック関数の署名が異なります。これは次のようになります DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
。– racl101

45

あなたが本当に気にするのは、迅速なデバッグのための実際のクエリ(最後の実行)だけです:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

$lcWhatYouWant = $laQuery[0]['query']; # <-------

# optionally disable the query log:
DB::disableQueryLog();

行うprint_r()上での$laQuery[0]バインディングを含む、完全なクエリを取得します。(上の$lcWhatYouWant変数は、変数がに置き換えられます??

メインのmysql接続以外のものを使用している場合は、代わりにこれらを使用する必要があります。

DB::connection("mysql2")->enableQueryLog();

DB::connection("mysql2")->getQueryLog();

(「mysql2」が接続名にある場合)


1
このコードはどこに行きますか?(5.4)コントローラ、モデルを試し、ミドルウェアを調べましたが、dbエラーが発生する前にどこで実行すればよいかわかりません。
blamb

実行を停止しているクエリを実行しているときにエラーが発生する場合は、エラーから問題の内容がわかります。エラーがオフになっている場合は、/ storage / log / laravelなどでエラーログを確認できます。(現時点では自分のコンピューターではありません)回答で提案したコードの実行中にエラーが発生していると言っている場合は、コードを実行している場所に必ずDBファサードを含めてください。何をしようとしているのかわからないが、コントローラーはあなたが言及したオプションの中で最も正しいように聞こえる。(私は通常、個別のヘルパークラスでクエリを実行します)
Skeets '19

14

これをroutes.phpファイルに置きます:

\Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
    echo'<pre>';
    var_dump($query->sql);
    var_dump($query->bindings);
    var_dump($query->time);
    echo'</pre>';
});

msurguyによって送信された、このページのソースコード。コメントには、laravel 5.2のこの修正コードが記載されています。


少し汚いですが、$ query-> bindingsと$ query-> timeヒントに対して+1
Paolo Stefan

きちんと!これを使用すると、クエリが発生している場所のビューに結果が表示されます。
Charles Wood

14

最初にクエリログを有効にする必要があります

DB::enableQueryLog();

次に、単純にクエリログを取得できます。

dd(DB::getQueryLog());

アプリケーションを開始する前にクエリログを有効にすると、BeforeMiddlewareで実行でき、実行したクエリをAfterMiddlewareで取得できます。


11

どうやらLaravel 5.2では、クロージャーはDB::listen単一のパラメーターのみを受け取ります。

したがって、DB::listenLaravel 5.2で使用する場合は、次のようにする必要があります。

DB::listen(
    function ($sql) {
        // $sql is an object with the properties:
        //  sql: The query
        //  bindings: the sql query variables
        //  time: The execution time for the query
        //  connectionName: The name of the connection

        // To save the executed queries to file:
        // Process the sql and the bindings:
        foreach ($sql->bindings as $i => $binding) {
            if ($binding instanceof \DateTime) {
                $sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
            } else {
                if (is_string($binding)) {
                    $sql->bindings[$i] = "'$binding'";
                }
            }
        }

        // Insert bindings into query
        $query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);

        $query = vsprintf($query, $sql->bindings);

        // Save the query to file
        $logFile = fopen(
            storage_path('logs' . DIRECTORY_SEPARATOR . date('Y-m-d') . '_query.log'),
            'a+'
        );
        fwrite($logFile, date('Y-m-d H:i:s') . ': ' . $query . PHP_EOL);
        fclose($logFile);
    }
);

古いLaravelの場合、私は自分のソリューションをstackoverflow.com/a/44920198/3823826
Csongor Halmai 2017


5

そうではtoSql()なく代わりに使用してくださいget()

$users = User::orderBy('name', 'asc')->toSql();
echo $users;
// Outputs the string:
'select * from `users` order by `name` asc'

2

(Laravel 5.2)最も簡単な方法は、SQLクエリを監視するコード行を1行追加することです。

\DB::listen(function($sql) {var_dump($sql); });

1

どうやらLaravel 5.2で続行すると、DB :: listenのクロージャーは単一のパラメーターのみを受け取ります...上記の応答:このコードをミドルウェアスクリプトに入れ、ルートで使用できます。

さらに:

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('sql');
$log->pushHandler(new StreamHandler(storage_path().'/logs/sql-' . date('Y-m-d') . '.log', Logger::INFO));

// add records to the log
$log->addInfo($query, $data);

どの部分をミドルウェアに配置する必要がありますか?どのルートで?
user1016265

1

このコードは:

  • Laravel 5.2
  • ステートメントをmysqlデータベースにログインします。

@milzの回答に基づくコードは次のとおりです。

    DB::listen(function($sql) {
        $LOG_TABLE_NAME = 'log';
        foreach ($sql->bindings as $i => $binding) {
            if ($binding instanceof \DateTime) {
                $sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
            } else {
                if (is_string($binding)) {
                    $sql->bindings[$i] = "'$binding'";
                }
            }
        }
        // Insert bindings into query
        $query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);
        $query = vsprintf($query, $sql->bindings);
        if(stripos($query, 'insert into `'.$LOG_TABLE_NAME.'`')===false){
            $toLog = new LogModel();
            $toLog->uId = 100;
            $toLog->sql = $query;
            $toLog->save();
        }
    });

コアは、SQLステートメントをデータベースif(stripos...に挿入する再帰を防ぐ行insert into logです。


0

私はこの記事にある答えを考えています:https : //arjunphp.com/laravel-5-5-log-eloquent-queries/

クエリロギングを実現するのは高速で簡単です。

メソッドにコールバックを追加してAppServiceProviderbootDBクエリをリッスンするだけです。

namespace App\Providers;

use DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        DB::listen(function($query) {
            logger()->info($query->sql . print_r($query->bindings, true));
        });
    }
}

0

次のステートメントのSQLクエリを印刷するとします。

$user = User::find(5);

次のようにするだけです。

DB::enableQueryLog();//enable query logging

$user = User::find(5);

print_r(DB::getQueryLog());//print sql query

これにより、Laravelで最後に実行されたクエリが出力されます。


-3

laravel 5以降では、DB :: getQueryLog()のみを使用すると、機能しません。これによりデフォルトでの値

 protected $loggingQueries = false;

に変更

protected $loggingQueries = true; 

クエリを記録するために以下のファイルにあります。

/vendor/laravel/framework/src/illuminate/Database/Connection.php 

そしてDB::getQueryLog()、クエリを印刷する場所を使用できます。


1
vendorファイルを編集するのは悪い考えです。彼らはオリジナルのままにしておく必要があります。
shukshin.ivan 2017

@ shukshin.ivanはい、ベンダーファイルを編集してはなりませんが、正確なクエリを取得するには、このコードをしばらく編集してから、元に戻すことができます。
Rupali Pemare 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.