簡體   English   中英

如何在 Laravel 5 中執行查詢? DB::getQueryLog() 返回空數組

[英]How to Get the Query Executed in Laravel 5? DB::getQueryLog() Returning Empty Array

我正在嘗試查看查詢日志,但DB::getQueryLog()只是返回一個空數組:

$user = User::find(5);
print_r(DB::getQueryLog());

結果

Array
(
)

如何查看此查詢的日志?

默認情況下,在 Laravel 5 中禁用查詢日志: https ://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

您需要通過調用以下命令啟用查詢日志:

DB::enableQueryLog();

// and then you can get query log

dd(DB::getQueryLog());

或者注冊一個事件監聽器:

DB::listen(
    function ($sql, $bindings, $time) {
        //  $sql - select * from `ncv_users` where `ncv_users`.`id` = ? limit 1
        //  $bindings - [5]
        //  $time(in milliseconds) - 0.38 
    }
);  

一些技巧

1.多個數據庫連接

如果您有多個數據庫連接,則必須指定要記錄的連接

my_connection啟用查詢日志:

DB::connection('my_connection')->enableQueryLog();

獲取my_connection的查詢日志:

print_r(
   DB::connection('my_connection')->getQueryLog()
);

2、在哪里啟用查詢日志?

對於 HTTP 請求生命周期,您可以在某些 `BeforeAnyDbQueryMiddleware` [中間件][1] 的 `handle` 方法中啟用查詢日志,然后在同一中間件的 [`terminate`][2] 方法中檢索已執行的查詢。
 class BeforeAnyDbQueryMiddleware { public function handle($request, Closure $next) { DB::enableQueryLog(); return $next($request); } public function terminate($request, $response) { // Store or dump the log data... dd( DB::getQueryLog() ); } }

中間件鏈不會為 artisan 命令運行,因此對於 CLI 執行,您可以在artisan.start事件偵聽器中啟用查詢日志。

例如你可以把它放在bootstrap/app.php文件中

$app['events']->listen('artisan.start', function(){ \DB::enableQueryLog(); });

3.內存

Laravel 將所有查詢保存在內存中。 所以在某些情況下,例如當插入大量行時,或者有大量查詢的長時間運行的作業時,這可能會導致應用程序使用過多的內存。

在大多數情況下,您只需要在調試時使用查詢日志,如果是這種情況,我建議您只在開發時啟用它。

 if (App::environment('local')) { // The environment is local DB::enableQueryLog(); }

參考

如果您真正關心的是用於快速調試目的的實際查詢(最后一次運行):

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

$lcWhatYouWant = $laQuery[0]['query']; # <-------

# optionally disable the query log:
DB::disableQueryLog();

$laQuery[0]上執行print_r()以獲得完整的查詢,包括綁定。 (上面的$lcWhatYouWant變量會將變量替換為??

如果您使用的不是主 mysql 連接,則需要改用這些連接:

DB::connection("mysql2")->enableQueryLog();

DB::connection("mysql2")->getQueryLog();

(用你的連接名稱,其中“mysql2”是)

您需要先啟用查詢日志記錄

DB::enableQueryLog();

然后你可以通過簡單地獲取查詢日志:

dd(DB::getQueryLog());

如果您在應用程序啟動之前啟用查詢日志記錄會更好,您可以在 BeforeMiddleware 中執行此操作,然后在 AfterMiddleware 中檢索已執行的查詢。

將其放在 routes.php 文件中:

\Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
    echo'<pre>';
    var_dump($query->sql);
    var_dump($query->bindings);
    var_dump($query->time);
    echo'</pre>';
});

由 msurguy 提交, 本頁源代碼。 你會在評論中找到 laravel 5.2 的修復代碼。

顯然在 Laravel 5.2 中, DB::listen中的閉包只接收一個參數。

所以,如果你想在 Laravel 5.2 中使用DB::listen ,你應該這樣做:

DB::listen(
    function ($sql) {
        // $sql is an object with the properties:
        //  sql: The query
        //  bindings: the sql query variables
        //  time: The execution time for the query
        //  connectionName: The name of the connection

        // To save the executed queries to file:
        // Process the sql and the bindings:
        foreach ($sql->bindings as $i => $binding) {
            if ($binding instanceof \DateTime) {
                $sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
            } else {
                if (is_string($binding)) {
                    $sql->bindings[$i] = "'$binding'";
                }
            }
        }

        // Insert bindings into query
        $query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);

        $query = vsprintf($query, $sql->bindings);

        // Save the query to file
        $logFile = fopen(
            storage_path('logs' . DIRECTORY_SEPARATOR . date('Y-m-d') . '_query.log'),
            'a+'
        );
        fwrite($logFile, date('Y-m-d H:i:s') . ': ' . $query . PHP_EOL);
        fclose($logFile);
    }
);

像這樣使用toSql()而不是get()

$users = User::orderBy('name', 'asc')->toSql();

echo $users;

// Outputs the string:
'select * from `users` order by `name` asc'

對於laravel 5.8 ,你只需添加dddump

前任:

DB::table('users')->where('votes', '>', 100)->dd();

要么

DB::table('users')->where('votes', '>', 100)->dump();

參考: https ://laravel.com/docs/5.8/queries#debugging

(Laravel 5.2) 我發現最簡單的方法就是添加一行代碼來監控 sql 查詢:

\DB::listen(function($sql) {var_dump($sql); });

查詢執行

\Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {          
            $sql = $query->sql; 
            $time = $query->time;
            $connection = $query->connection->getName();
 
            Log::debug('query : '.$sql);
            Log::debug('time '.$time);
            Log::debug('connection '.$connection);
        });

詢問

StaffRegister::all();

輸出

[2021-03-14 08:00:57] local.DEBUG: query : select * from `staff_registers`  
[2021-03-14 08:00:57] local.DEBUG: time 0.93  
[2021-03-14 08:00:57] local.DEBUG: connection mysql  

完整的結構

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Log;
use App\Models\StaffRegister;

class AuthController extends Controller
{
   public function index(){
   
       \Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
      
           $sql = $query->sql; 
           $time = $query->time;
           $connection = $query->connection->getName();

           Log::debug('query : '.$sql);
           Log::debug('time '.$time);
           Log::debug('connection '.$connection);
       });

       $obj = StaffRegister::all(); 
    
       return $obj;
   }
}

GET REPOSNSE 的准確方法

顯然在 Laravel 5.2 中,DB::listen 中的閉包僅接收一個參數...上面的響應:您可以將此代碼放入中間件腳本中並在路由中使用它。

此外:

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('sql');
$log->pushHandler(new StreamHandler(storage_path().'/logs/sql-' . date('Y-m-d') . '.log', Logger::INFO));

// add records to the log
$log->addInfo($query, $data);

此代碼用於:

  • 拉維爾 5.2
  • 將語句記錄到mysql數據庫中

這是基於@milz 的回答的代碼:

    DB::listen(function($sql) {
        $LOG_TABLE_NAME = 'log';
        foreach ($sql->bindings as $i => $binding) {
            if ($binding instanceof \DateTime) {
                $sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
            } else {
                if (is_string($binding)) {
                    $sql->bindings[$i] = "'$binding'";
                }
            }
        }
        // Insert bindings into query
        $query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);
        $query = vsprintf($query, $sql->bindings);
        if(stripos($query, 'insert into `'.$LOG_TABLE_NAME.'`')===false){
            $toLog = new LogModel();
            $toLog->uId = 100;
            $toLog->sql = $query;
            $toLog->save();
        }
    });

核心是if(stripos...行,它防止將insert into log sql 語句插入數據庫的遞歸。

假設您要打印以下語句的 SQL 查詢。

$user = User::find(5);

你只需要做如下:

DB::enableQueryLog();//enable query logging

$user = User::find(5);

print_r(DB::getQueryLog());//print sql query

這將打印 Laravel 中最后執行的查詢。

我認為答案位於這篇文章中: https ://arjunphp.com/laravel-5-5-log-eloquent-queries/

實現查詢日志記錄快速簡單。

您只需要在boot方法中的AppServiceProvider添加一個回調來監聽數據庫查詢:

namespace App\Providers;

use DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        DB::listen(function($query) {
            logger()->info($query->sql . print_r($query->bindings, true));
        });
    }
}

將此函數添加到您的幫助程序文件中並簡單地調用。

function getRawQuery($sql){
        $query = str_replace(array('?'), array('\'%s\''), $sql->toSql());
        $query = vsprintf($query, $sql->getBindings());     
        return $query;
}

輸出: "select * from user where status = '1' order by id desc limit 25 offset 0"

對於 laravel 5 及以后的版本,僅使用 DB::getQueryLog() 是行不通的。 BY 默認值

 protected $loggingQueries = false;

改成

protected $loggingQueries = true; 

在下面的文件中進行日志記錄查詢。

/vendor/laravel/framework/src/illuminate/Database/Connection.php 

然后我們可以在要打印查詢的地方使用DB::getQueryLog()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM