新建 app/Listeners/SqlListener.php 监听器,代码如下:

<?php

namespace App\Listeners;

use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\Process\PhpExecutableFinder;
use Throwable;

class SqlListener
{

    /**
     * @var Request
     */
    private $request;

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Handle the event.
     *
     * @param QueryExecuted $event
     * @return void
     */
    public function handle(QueryExecuted $event)
    {
        if (config('app.debug') == false) {
            return;
        }

        try {
            $bindings = $event->connection->prepareBindings($event->bindings);
            foreach ($bindings as $key => $value) {
                if (!is_int($value)) {
                    if (is_null($value)) {
                        $value = 'null';
                    } else {
                        $value = "'".addslashes($value)."'";
                        $value = str_replace(["\r", "\n"], ['\r', '\n'], $value);
                    }
                    $bindings[$key] = $value;
                }
            }
            $sql = str_replace(['%', '?'], ['%%', '%s'], $event->sql);
            $sql = vsprintf($sql, $bindings);
            // 不记录 admin_* 表
            // if (Str::is('*`admin_*`*', $sql)) {
            //     return;
            // }
            if (app()->runningInConsole()) {
                $method = 'CLI';
                $uri = (new PhpExecutableFinder)->find(false);
                foreach ($this->request->server('argv') as $arg) {
                    $uri .= ' '.escapeshellarg($arg);
                }
            } else {
                $method = $this->request->getMethod();
                $uri = $this->request->getRequestUri();
            }
            $now = now();
            $logTime = $now->format('Y-m-d H:i:s');
            $logDate = $now->format('Y-m-d');
            $runTime = $event->time;
            $log = "[$logTime] $method: $uri, Time: {$runTime}ms".PHP_EOL.$sql.PHP_EOL.PHP_EOL;
            $file = storage_path('logs/sql-'.$logDate.'.log');
            file_put_contents($file, $log, FILE_APPEND);
        } catch (Throwable $e) {
            Log::error($e->getMessage().PHP_EOL.$e->getTraceAsString());
        }
    }
}

再编辑 app/Providers/EventServiceProvider.php 文件,在 $listen 数组中添加这个 SQL 监听器:

    protected $listen = [
        \Illuminate\Database\Events\QueryExecuted::class => [
            \App\Listeners\SqlListener::class,
        ],
    ];

这样就可以了,当我们处于 debug 模式时,SQL 语句会被记录到 storage/logs/sql-年-月-日.log 文件里。