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?

Arsen
źródło
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

Marty Aghajanyan
źródło
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
1
Laravel 5.2, patrz: laravel.com/docs/5.2/database#listening-for-query-events
Dmitri Chebotarev
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)

Skeets
źródło
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.

Rubén Ruíz
źródło
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.

Vineet Garg
źródło
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);
    }
);
Luís Cruz
źródło
W przypadku starszego Laravel dodałem swoje rozwiązanie do stackoverflow.com/a/44920198/3823826
Csongor Halmai,
8

W przypadku laravel 5.8 wystarczy dodać dd lub dump .

Dawny:

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

lub

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

odniesienie: https://laravel.com/docs/5.8/queries#debugging

larp
źródło
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'
doncadavona
źródło
2

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

\DB::listen(function($sql) {var_dump($sql); });
ChrisH
źródło
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);
Święty Ojcze
źródło
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.

ch271828n
źródło
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));
        });
    }
}
Javier Núñez
źródło
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.

Gufran Hasan
źródło
-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.

Rupali Pemare
źródło
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