17
2019

LaravelでSQLログを出力する

CATEGORYPHP
最近続くLaravelネタ。今回はデバッグ用のSQLログの出し方について。試したバージョンは5.8。

まず結論から。辿り着いた個人的最適解はこれ。これをこんな感じにEventServiceProvider辺りに入れてください。
\DB::listen(function ($ev) {
\Log::debug("DB({$ev->connectionName}): {$ev->sql}; bindings=" . \json_encode($ev->connection->prepareBindings($ev->bindings)) . ' time=' . sprintf("%.2fms", $ev->time));
});
Event::listen('Illuminate\Database\Events\TransactionBeginning', function ($ev) {
\Log::debug("DB({$ev->connectionName}): start transaction");
});
Event::listen('Illuminate\Database\Events\TransactionCommitted', function ($ev) {
\Log::debug("DB({$ev->connectionName}): commit");
});
Event::listen('Illuminate\Database\Events\TransactionRolledBack', function ($ev) {
\Log::debug("DB({$ev->connectionName}): rollback");
});
以下解説。LaravelではデバッグログをONにしたら自動でSQLログが出てくる…という仕組みは無いみたいなので、SQL実行時のイベントを受け取って手動でログを出力する。
Connection::enableQueryLog() というメソッドはあるが、これはDB::listen()のタイミングでメモリ上に同じ内容を保存するだけっぽいので、特に使うメリットなさそうだった。)

次いで、トランザクションの開始終了は↑のイベントでは取れないので、別途こちらもイベントを受け取って手動でログ出力する。

さらに3つ目。SQLのバインド変数が入ってくる$ev->bindingsだが、ここには実際のSQLに渡されるキャストされた値、ではなくキャスト前の値が入ってくるので、prepareBindings()を通して、出来るだけ実際の値にする。
DateTimeInterfaceとかboolとか以外のインスタンスはそのままだけど…。)


以上、LaravelのSQLログの出し方をググるといろいろページが出てくるけど、その通りにやったら3つ目が抜けてて見事にハマったのでまとめてみた。参考までに。
スポンサーサイト



Tag: PHP Laravel

0 Comments

Leave a comment