月別アーカイブ: 2025年9月

Laravel 操作した時に流れるDBログを取る

Kernelで全ルートに効かせてログを取らない時はKernelからコメントアウト
アーキテクチャありの大規模PJでソースが追いきれない場合に有効
外部キーとか張っていない等
どこにどんなデータができたのかをサクッと把握できる

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class LogDbWritesOnce
{
    public function handle($request, Closure $next)
    {
        $writes = [];
        DB::listen(function ($q) use (&$writes) {
            $sql = $q->sql;
            if (preg_match('/^\s*(insert|update|delete|replace|truncate|create|alter|drop)\b/i', $sql)) {
                $writes[] = [
                    'op'  => strtoupper(strtok(trim($sql), ' ')),
                    'sql' => self::interpolate($sql, $q->bindings),
                ];
            }
        });

        $res = $next($request);
        foreach ($writes as $w) Log::channel('dbwrites')->info('DB write', $w);
        return $res;
    }

    private static function interpolate(string $sql, array $b): string
    {
        if (!$b) return $sql;
        $parts = explode('?', $sql);
        $out = array_shift($parts);
        foreach ($b as $v) $out .= self::q($v) . array_shift($parts);
        return $out;
    }

    private static function q($v): string
    {
        if ($v === null) return 'NULL';
        if (is_bool($v)) return $v ? '1' : '0';
        if (is_int($v) || is_float($v)) return (string)$v;
        $s = str_replace("'", "''", (string)$v);
        if (strlen($s) > 200) $s = substr($s, 0, 200) . '…';
        return "'{$s}'";
    }
}

config/logging.php

return [
    'channels' => [
        // 既存の channels がたくさん並んでいるはず…

        // ↓↓↓ これを末尾に追加 ↓↓↓
        'dbwrites' => [
            // 日毎に分けたいなら "daily"、1ファイル固定なら "single"
            'driver' => 'daily',
            'path'   => storage_path('logs/db-writes.log'),
            'level'  => 'info',
            'days'   => 14,
        ],
        // ↑↑↑ ここまで追加 ↑↑↑
    ],
];

app/Http/Kernel.php

protected $routeMiddleware = [
    // 既存…
    'log.writes' => \App\Http\Middleware\LogDbWritesOnce::class,
];