laravel打印sql

快捷打印 Laravel 中的數據庫查詢(SQL)語句

 5天前 ⋅  375 ⋅  11 ⋅  11laravel

閒話少敘,直接入題。首先,爲何要打印 Laravel 中 Query Builder 構建的 SQL 語句?sql

答案很簡單,就是我要知道到底執行了什麼 SQL 語句,這樣我就能合適地寫 Query Builder、在適合用『熱加載』的場景不會誤用『懶加載』。數據庫

熱加載#

$user = User::where('name', 'Eric')->with('articles')->first();

上面就是熱加載的例子――獲取第一個名爲『Eric』的用戶信息同時,把他的文章也全都取到。閉包

這樣的使用場景下,Query Builder 只使用了相似下面的兩條 SQL 語句。ide

  1. select * from users where name = 'Eric' limit 1;
  2. select * from articles where user_id in (22);

就是說當你用 $user->articles 遍歷用戶文章時,不會再請求數據庫了。post

懶加載#

懶加載和熱加載是相對的。下面就是懶加載的例子。ui

$user = User::where('name', 'Eric')->first();

// 在 Blade 模版裏遍歷打印出用戶文章
@\foreach($user->posts as $post)
    // ...
@endforeach

這種用法能達到效果,可是效率會變低――每次遍歷、處理的一篇文章信息,都是向數據庫執行一次 SQL 獲得的。spa

若是用戶有 N 篇文章,就要執行 N 次 SQL 查詢,再加上以前請求用戶信息的 1 次 SQL,這就是所謂的『N+1』問題。debug

明明能 2 次完成的事,就不要再花 N+1 次了。code

打印 SQL#

像上面的情況,若是咱們知道底層是怎樣執行 SQL 語句的,也許就不會發生了。這就爲咱們找出了一個有必要打印 SQL 語句來看的理由。

既然文章題目是『快捷打印 SQL』,天然配置起來也很簡單。配置到最後的結果的是:

當你的 APP_ENV 設置爲 local、請求 URL 後面緊跟 ?sql-debug=1 時,就會打印出請求處理邏輯中涉及到的全部數據庫查詢語句。

配置#

AppServiceProvider 的 boot 方法內寫入

use DB;
use Event;

if ( env('APP_ENV') === 'local' ) {
    DB::connection()->enableQueryLog();
    Event::listen('kernel.handled', function ( $request, $response ) {
        if ( $request->has('sql-debug') ) {
            $queries = DB::getQueryLog();
            if (!empty($queries)) {
                foreach ($queries as &$query) {
                    $query['full_query'] = vsprintf(str_replace('?', '%s', $query['query']), $query['bindings']);
                }
            }
            dd($queries);
        }
    });
}

注意:路由有兩種形式——基於閉包(Closure)和基於控制器動做(Controller Action)的。上面的配置只對基於控制器動做的路由有效

相關文章
相關標籤/搜索