Log all Eloquent Queries
PHP:7.2
Laravel:5.7
在開發的過程中,很常會遇到一些奇怪的資料庫問題,可能是從 DB 拉出來的資料有錯、可能直接噴 SQL 的 error,如果 SQL query 很複雜,更難找到問題的原因。
因此,適當的紀錄相關資訊在開發上是非常有幫助的,而資料庫相關的問題,最直接的做法就是 log SQL query ,通常只要找出完整的 SQL query,很快就可以找到問題的原因了。
Create ServiceProvider
Log SQL query 這件事應該要是全域的,因此可以直接建立一個專門處理這件事的 ServiceProvider
。
利用 Artisan 建立 QueryLogServiceProvider
./artisan make:provider QueryLogServiceProvider
Register QueryLogServiceProvider
config/app.php
/*
* Application Service Providers...
*/
App\Providers\QueryLogServiceProvider::class,
Format Query
Laravel Eloquent
中的 SQL query 都有做資料的 escape,因此資料會分成 Escape Query
(變數都會被 ?
取代) 跟 Binding Data
,如果想看的仔細一點,可以自己手動針對資料做一些調整,變成可以直接貼在 command 的 SQL query。
app/Providers/QueryLogServiceProvider.php
public function boot()
{
// Listening for query events
\DB::listen(function ($query) {
// Escape Query
$sql = $query->sql;
// Binding Data
$bindings = $query->bindings;
// Spend Time
$time = $query->time;
// 針對 Binding 資料進行格式的處理
// 例如字串就加上引號
foreach ($bindings as $index => $binding) {
if (is_bool($binding)) {
$bindings[$index] = ($binding) ? ('1') : ('0');
} elseif (is_string($binding)) {
$bindings[$index] = "'$binding'";
}
}
// 依據將 ? 取代成 Binding Data
$sql = preg_replace_callback('/\?/', function () use (&$bindings) {
return array_shift($bindings);
}, $sql);
// 寫入 storage/logs/laravel.log
\Log::info($sql);
});
}
完成之後就可以在 storage/logs/laravel.log
看到相關的 SQL query log 了。