Laravel SQLのログをカスタムログチャンネルで別ファイルに出力させる
- クエリビルダとか使うけど、実際に発行されたSQL文とバインドパラメータをログに出したい
 - アプリのログと一緒ぢゃなくて別ファイル 
sql.logに出したいし、日ごとにログローテートしたい 
手順1. カスタムログチャンネルを作成する
作り方は公式マニュアルを参考にした。
(※すみません。手元のLaravelが5.7だと思って5.7のマニュアルを読んでたのですが、後で確認したら5.8でした。なので上に書いたLaravelのバージョンと相違があります。)
ここでは config/logging.php の channels の一番下に、sqlQueryLog なるカスタムチャンネルを追加する。
'channels' => [
    ...
    'sqlQueryLog' => [
        'driver' => 'custom',
        'via' => App\Logging\CreateSQLQueryLogger::class,
        'path' => storage_path('logs/sql.log'),
        'level' => 'debug',  // ログレベル debug 以上だけ出力
        'days' => 14,        // 14日分のログを保持する
    ],
],sqlQueryLog は私が勝手につけた名前なので、べつに好きな名前でよい。必要なのは driver に custom を指定するのと、via にMonologインスタンスを生成するためのクラス (※まだ無い。今から作る) を指定すること。
というわけで App\Logging\CreateSQLQueryLogger を作る。これはカスタムチャンネル用のMonologインスタンスを生成するためのクラスで、Monolog\Logger を返す __invoke() メソッドが必要。
<?php echo '<?php'; ?>
namespace App\Logging;
use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\LineFormatter;
class CreateSQLQueryLogger
{
    /**
     * SQLクエリ用Monologインスタンス生成
     * @param  array  $config
     * @return \Monolog\Logger
     */
    public function __invoke(array $config)
    {
        // 引数の $config には、config/logging.php で sqlQueryLog に設定した path とか days とかが入ってる!
        // 'debug' とかの文字列をMonologが使えるログレベルに変換
        $level = Logger::toMonologLevel($config['level']);
        // 日ごとにログローテートするハンドラ作成
        $hander = new RotatingFileHandler($config['path'], $config['days'], $level);  
        // 改行コードを出力する&カラのコンテキストを出力しないフォーマッタを設定
        $hander->setFormatter(new LineFormatter(null, null, true, true));
        // Monologインスタンス作成してハンドラ設定して返却
        $logger = new Logger('SQL');  // ロガー名は 'SQL' にした。これはログに出力される
        $logger->pushHandler($hander);
        return $logger;
    }
}このクラス名も私がマニュアルを参考に勝手につけた名前なので、どんな名前でも構わないはず。
__invoke() が返すMonologインスタンスは好みで作ればよい。ここでは「日ごとにログローテート (保持日数は days で設定)」「改行コードを出力する」「カラのコンテキストは無視する」ようなやつにした。
これでカスタムログチャンネルはできあがり。アプリ内のどこかしらで以下のように書くと、sqlQueryLog チャンネルを通って、storage/logs/sql-YYYY-MM-DD.log ファイルにログが出力される。
\Log::channel('sqlQueryLog')->debug('!!!!!');[2019-08-23 12:39:35] SQL.DEBUG: !!!!!  手順2. SQLクエリをログ出力させる
公式マニュアルの以下ページに DB::listen() でSQLクエリを取得する方法が書いてあるので、これを使う。
起動時に呼ばれるサービスプロバイダ AppServiceProvider の boot() で、以下のようにクエリリスナを登録する。クエリリスナの中で、先ほど作ったカスタムログチャンネル sqlQueryLog にSQLクエリを出力させる。
<?php echo '<?php'; ?>
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
    // 略
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        \DB::listen(function($query) {
            $str = $query->time.' ms -> '.$query->sql;
            if ($query->bindings) {
                $str .= "\n".'bind: '.var_export($query->bindings, true);
            }
            \Log::channel('sqlQueryLog')->debug($str);
        });
    }
}↑のコードはちょっとごちゃごちゃしてるけど、各情報は以下の通りに取得できるので、フォーマットは好きな感じで。
$query->time... 実行時間ミリ秒 (float)$query->sql... 実際のSQL文 (string)$query->bindings... バインドパラメータ (array)
あとはアプリ内のどこかしらで以下のようにクエリ実行すると、storage/logs/sql-YYYY-MM-DD.log ファイルに実行時間・実際のSQL文・バインドパラメータが出力される。
\DB::table('mytable')->where('id', 1)->get();[2019-08-23 18:30:27] SQL.DEBUG: 89.67 ms -> select * from "mytable" where "id" = ?
bind: array (
  0 => 1,
)  もちろん普通に \Log::debug() とかで書いたログは、従来通り laravel.log とかに出力される。
参考にさせていただいた記事
PHPのロガーMonologを理解しよう | QUARTETCOM TECH BLOG
 キリウ君が読まないノート