Jak uzyskać wykonanie zapytania w Laravel 5? DB :: getQueryLog () Zwraca pustą tablicę


172

Próbuję wyświetlić dziennik dla zapytania, ale DB::getQueryLog()po prostu zwraca pustą tablicę:

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

Wynik

Array
(
)

Jak mogę wyświetlić dziennik dla tego zapytania?


Laravel Debugbar to świetne narzędzie do rejestrowania zapytań. Ma również wiele innych niesamowitych funkcji.
— totymedli,

Odpowiedzi:


256

Domyślnie dziennik zapytań jest wyłączony w Laravel 5: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

Będziesz musiał włączyć dziennik zapytań, dzwoniąc:

DB::enableQueryLog();

lub zarejestruj odbiornik zdarzeń:

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

Kilka porad

1. Wiele połączeń DB

Jeśli masz więcej niż jedno połączenie DB, musisz określić, które połączenie ma być rejestrowane

Aby włączyć dziennik zapytań dla my_connection:

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

Aby uzyskać dziennik zapytań dla my_connection:

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

2. Gdzie włączyć dziennik zapytań?

W przypadku cyklu życia żądania HTTP można włączyć dziennik zapytań w handlemetodzie niektórych BeforeAnyDbQueryMiddleware oprogramowania pośredniego, a następnie pobrać wykonane zapytania w terminatemetodzie tego samego oprogramowania pośredniego.

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()
        );
    }
}

Łańcuch oprogramowania pośredniego nie będzie działał dla poleceń rzemieślniczych, więc w celu wykonania interfejsu wiersza polecenia można włączyć dziennik zapytań w artisan.startnasłuchiwaniu zdarzeń.

Na przykład możesz umieścić go w bootstrap/app.phppliku

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

3. Pamięć

Laravel przechowuje wszystkie zapytania w pamięci. Dlatego w niektórych przypadkach, na przykład podczas wstawiania dużej liczby wierszy lub w przypadku długotrwałego zadania z dużą liczbą zapytań, może to spowodować, że aplikacja zużyje nadmiar pamięci.

W większości przypadków będziesz potrzebować dziennika zapytań tylko do debugowania, a jeśli tak jest, zalecałbym włączenie go tylko do programowania.

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

Bibliografia


6
Jeśli twój system używa więcej niż jednego połączenia db, musisz je określić, w przeciwnym razie może zwrócić pustą tablicę:\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
— Diana R.

Opublikuj swój komentarz jako swoją odpowiedź @DianaR.
— Narendrasingh Sisodia


Jak włączyć rejestrowanie Eloquent "NameController :: create ();" komunikat?
— Rubén Ruíz

2
Zauważ, że w Laravel 5.4 DB::listenfunkcja zwrotna ma inną sygnaturę. To bardziej tak: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
— racl101

45

Jeśli wszystko, na czym naprawdę Ci zależy, to faktyczne zapytanie (ostatnie uruchomione) w celu szybkiego debugowania:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

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

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

zrobić print_r()ON $laQuery[0], aby uzyskać pełny zapytanie, włącznie z wiązaniami. ( $lcWhatYouWantzmienna powyżej będzie miała zmienne zastąpione przez ??)

Jeśli używasz czegoś innego niż główne połączenie mysql, musisz zamiast tego użyć tych:

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

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

(z nazwą połączenia, gdzie „mysql2” to)


1
gdzie jednak ten kod idzie? (5.4) Wypróbowałem kontroler, model i zajrzałem do oprogramowania pośredniego, nie byłem pewien, gdzie go wykonać, zanim pojawi się błąd db.
— blamb

Jeśli podczas wykonywania kwerendy zatrzymującej wykonywanie pojawia się błąd, powinien on powiedzieć, na czym polega problem. Jeśli masz wyłączone błędy, możesz sprawdzić logowanie błędów / storage / log / laravel lub coś w tym rodzaju. (W tej chwili nie ma mnie przy komputerze) Jeśli mówisz, że pojawia się błąd podczas wykonywania kodu, który zasugerowałem w mojej odpowiedzi, upewnij się, że uwzględniasz fasadę DB wszędzie tam, gdzie uruchamiasz kod. Nie jestem pewien, co próbujesz zrobić, ale kontroler brzmi jak najbardziej poprawna z wymienionych opcji. (Zwykle wykonuję zapytania w osobnych klasach pomocniczych)
— Skeets

14

Umieść to w pliku tours.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>';
});

Przesłane przez msurguy, kod źródłowy na tej stronie . Ten kod poprawki dla programu Laravel 5.2 można znaleźć w komentarzach.


Trochę brudne, ale +1 dla $ query-> bindings i $ query-> time hints
— Paolo Stefan

Schludny! Użycie tego pokazuje wyniki w widoku, dokładnie tam, gdzie występuje zapytanie!
— Charles Wood

14

Najpierw musisz włączyć rejestrowanie zapytań

DB::enableQueryLog();

Następnie możesz uzyskać dzienniki zapytań, po prostu:

dd(DB::getQueryLog());

Byłoby lepiej, gdybyś włączył rejestrowanie zapytań przed uruchomieniem aplikacji, co możesz zrobić w programie BeforeMiddleware, a następnie pobrać wykonane zapytania w AfterMiddleware.


11

Najwyraźniej w przypadku Laravel 5.2 zamknięcie DB::listenotrzymuje tylko jeden parametr.

Tak więc, jeśli chcesz używać DB::listenw Laravel 5.2, powinieneś zrobić coś takiego:

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);
    }
);

W przypadku starszego Laravel dodałem swoje rozwiązanie do stackoverflow.com/a/44920198/3823826
— Csongor Halmai,


5

Użyj toSql()zamiast get()tak:

$users = User::orderBy('name', 'asc')->toSql();
echo $users;
// Outputs the string:
'select * from `users` order by `name` asc'

2

(Laravel 5.2) Najprostszym sposobem jest dodanie jednej linii kodu w celu monitorowania zapytań sql:

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

1

Kontynuując działanie Apparently with Laravel 5.2, zamknięcie w DB :: Listen odbiera tylko jeden parametr ... odpowiedź powyżej: możesz umieścić ten kod w skrypcie oprogramowania pośredniego i używać go w trasach.

Do tego:

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);

która część powinna zostać umieszczona w oprogramowaniu pośrednim? które na trasach?
— user1016265

1

Ten kod jest przeznaczony dla:

  • Laravel 5.2
  • Zaloguj się do bazy danych mysql

Oto kod, który jest oparty na odpowiedzi @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();
        }
    });

Rdzeniem jest if(stripos...linia, która zapobiega rekursji podczas wstawiania instrukcji insert into logsql do bazy danych.


0

Myślę, że odpowiedź znajduje się w tym artykule: https://arjunphp.com/laravel-5-5-log-eloquent-queries/

jest szybki i prosty w rejestrowaniu zapytań.

Wystarczy dodać AppServiceProviderw bootmetodzie wywołanie zwrotne, aby nasłuchiwać zapytań DB:

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));
        });
    }
}

0

Załóżmy, że chcesz wydrukować zapytanie SQL zawierające następujące instrukcje.

$user = User::find(5);

Wystarczy wykonać następujące czynności:

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

$user = User::find(5);

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

Spowoduje to wydrukowanie ostatniego wykonanego zapytania w Laravel.


-3

Dla laravel 5 i nowszych, użycie tylko DB :: getQueryLog (), nie zadziała. BY domyślnie w tym wartość

 protected $loggingQueries = false;

zmień to na

protected $loggingQueries = true; 

w poniższym pliku do logowania zapytania.

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

Następnie możemy użyć miejsca, w DB::getQueryLog()którym chcesz wydrukować zapytanie.


1
Edycja vendorplików to zły pomysł . Muszą być oryginalne.
— shukshin.ivan

@ shukshin.ivan Tak, nie wolno edytować plików dostawców, ale aby uzyskać dokładne zapytanie, na razie edytujemy ten kod, możemy go przywrócić.
— Rupali Pemare
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.