• 投稿日:2022年09月14日 14時12分19秒
  • 更新日:2022年09月14日 14時12分50秒
【Laravel】SQLログを別ファイルに出力

【Laravel】SQLログを別ファイルに出力

詳細

参考サイト様のほぼコピペです。

対応内容

DataBaseQueryServiceProviderを作成

php artisan make:provider DataBaseQueryServiceProvider

これで「app/Providers/DataBaseQueryServiceProvider.php」が作成されます

.envの確認と追記

確認する項目と追記する項目のみを記載

LOG_CHANNEL=stack   #値を確認
LOG_SQL_ENABLE=true #追記

config/app.php へ追記

    'providers' => [
        // ... 省略
        App\Providers\DataBaseQueryServiceProvider::class,
    ],

config/logging.phpへ追記

ログ設定のチャネルに「sql」を追加し、stackチャネル選択時に使うチャネルとします。
そして.envに追加したLOG_SQL_ENABLEの値によって制御するようにします(設定が無ければ有効です)


    'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['stack', 'sql'],
            'ignore_exceptions' => false,
        ],
        // ... 省略
        'sql' => [
            'driver' => 'daily',  // 日別
            'path' => storage_path('logs/sql.log'), // 出力先
            'level' => 'debug', // ログレベル
            //'days' => 14, // 保存期間
        ],
    ],
    'sql' => [
        'enable' => env('LOG_SQL_ENABLE', true),
    ],
];

DataBaseQueryServiceProviderの内容を編集

実際にログを出力するクラスです

<?php declare(strict_types=1);

namespace App\Providers;

use Carbon\Carbon;
use DateTime;
use Illuminate\Database\Events\TransactionBeginning;
use Illuminate\Database\Events\TransactionCommitted;
use Illuminate\Database\Events\TransactionRolledBack;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\ServiceProvider;

class DataBaseQueryServiceProvider extends ServiceProvider
{
    /**
     * Register services. Log::channel('sqllog')->debug(...);
     */
    public function register(): void
    {
        if (config('logging.sql.enable') === false) {
            return;
        }

        DB::listen(function ($query): void {
            $sql = $query->sql;

            foreach ($query->bindings as $binding) {
                if (is_string($binding)) {
                    $binding = "'{$binding}'";
                } elseif (is_bool($binding)) {
                    $binding = $binding ? '1' : '0';
                } elseif (is_int($binding)) {
                    $binding = (string) $binding;
                } elseif ($binding === null) {
                    $binding = 'NULL';
                } elseif ($binding instanceof Carbon) {
                    $binding = "'{$binding->toDateTimeString()}'";
                } elseif ($binding instanceof DateTime) {
                    $binding = "'{$binding->format('Y-m-d H:i:s')}'";
                }

                $sql = preg_replace('/\\?/', $binding, $sql, 1);
            }

            Log::channel('sql')->debug('SQL', ['sql' => $sql, 'time' => "{$query->time} ms"]);
        });

        Event::listen(TransactionBeginning::class, function (TransactionBeginning $event): void {
            Log::channel('sql')->debug('START TRANSACTION');
        });

        Event::listen(TransactionCommitted::class, function (TransactionCommitted $event): void {
            Log::channel('sql')->debug('COMMIT');
        });

        Event::listen(TransactionRolledBack::class, function (TransactionRolledBack $event): void {
            Log::channel('sql')->debug('ROLLBACK');
        });
    }
}

Logクラスのchannelにsqlを指定することで、sqlチェネルにのみ出力します。

最後に

SPECIAL THANKS

  1. Laravel SQLの実行クエリログを出力する -Qiita-
  2. 【Laravel】実行SQLをデフォルト以外のログファイルに出力する方法 -Zenn-
  3. Laravel 8.x ログ -Laravel-
Nginxでリバースプロキシを設定する
Laravelでリバースプロキシを使った場合のホスト名の指定方法
【Laravel】configファイルについて
Laravel Sailでサクッと環境構築
Laravelを使って開発したものを本番環境へ
Laravelをインストールし開発環境を整備する
Laravelのコマンドを色々まとめ
MySQLでよく使うSQL-ユーザ関係-