背景
Laravel 默认的日志记录只会记录日志信息,不会记录 SQL 查询记录,
只有在报错的时候才会记录 SQL 查询记录,这对于开发和调试来说是不够的。
这里我们可以通过 Laravel 的事件系统来监听 SQL 查询事件,然后将 SQL 查询记录到日志中。
方法
创建监听服务提供者
创建app\Providers\DataBaseQueryServiceProvider.php
内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| <?php
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 {
public function register() { $this->listenDB();
Event::listen(TransactionBeginning::class, function (TransactionBeginning $event): void { Log::debug('START TRANSACTION'); });
Event::listen(TransactionCommitted::class, function (TransactionCommitted $event): void { Log::debug('COMMIT'); });
Event::listen(TransactionRolledBack::class, function (TransactionRolledBack $event): void { Log::debug('ROLLBACK'); }); }
private function listenDB() { 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); }
$tracesText = (env('APP_ENV') == 'local') ? $this->getTrace() : '';
Log::debug('SQL', ['time' => "{$query->time} ms", 'sql' => $sql, 'Executed at' => $tracesText]); }); }
private function getTrace() { $traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 30); $tracesText = ''; $num = 0; foreach ($traces as $trace) { if (isset($trace['file']) && strpos($trace['file'], 'DataBaseQueryServiceProvider') !== false) { continue; } if (isset($trace['file']) && strpos($trace['file'], 'Illuminate') !== false) { continue; }
if (isset($trace['file']) && isset($trace['line'])) { $tracesText .= "\n[{$num}]" . $trace['file'] . ':' . $trace['line']; } $num++; }
return $tracesText; }
public function boot() { } }
|
注册服务提供者
在config/app.php中注册服务提供者
1 2 3 4 5
| 'providers' => [ App\Providers\DataBaseQueryServiceProvider::class, ];
|
结束
这样配置好之后,在Laravel中执行SQL查询时,就会自动记录到日志中。