Wie wird die Abfrage in Laravel 5 ausgeführt? DB :: getQueryLog () Gibt ein leeres Array zurück


171

Ich versuche, das Protokoll für eine Abfrage anzuzeigen, gebe aber DB::getQueryLog()nur ein leeres Array zurück:

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

Ergebnis

Array
(
)

Wie kann ich das Protokoll für diese Abfrage anzeigen?


Laravel Debugbar ist ein großartiges Tool zum Protokollieren der Abfragen. Es hat auch viele andere tolle Funktionen.
Totymedli

Antworten:


256

Standardmäßig ist das Abfrageprotokoll in Laravel 5 deaktiviert: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

Sie müssen das Abfrageprotokoll aktivieren, indem Sie Folgendes aufrufen:

DB::enableQueryLog();

oder registrieren Sie einen Ereignis-Listener:

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

Einige Hinweise

1. Mehrere DB-Verbindungen

Wenn Sie mehr als eine DB-Verbindung haben, müssen Sie angeben, welche Verbindung protokolliert werden soll

So aktivieren Sie das Abfrageprotokoll für my_connection:

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

So erhalten Sie ein Abfrageprotokoll für my_connection:

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

2. Wo kann das Abfrageprotokoll aktiviert werden?

Für einen HTTP-Anforderungslebenszyklus können Sie das Abfrageprotokoll in der handleMethode einiger BeforeAnyDbQueryMiddleware Middleware aktivieren und dann die ausgeführten Abfragen in der terminateMethode derselben Middleware abrufen .

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

Die Kette einer Middleware wird nicht für handwerkliche Befehle ausgeführt. Daher können Sie für die CLI-Ausführung das Abfrageprotokoll im artisan.startEreignis-Listener aktivieren .

Zum Beispiel können Sie es in die bootstrap/app.phpDatei einfügen

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

3. Speicher

Laravel speichert alle Abfragen. In einigen Fällen, z. B. beim Einfügen einer großen Anzahl von Zeilen oder bei einem lang laufenden Job mit vielen Abfragen, kann dies dazu führen, dass die Anwendung überschüssigen Speicher verwendet.

In den meisten Fällen benötigen Sie das Abfrageprotokoll nur zum Debuggen. In diesem Fall würde ich empfehlen, es nur für die Entwicklung zu aktivieren.

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

Verweise


6
Wenn Ihr System mehr als eine Datenbankverbindung verwendet, müssen Sie diese angeben, andernfalls wird möglicherweise ein leeres Array zurückgegeben:\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
Diana R.

Veröffentlichen Sie Ihren Kommentar als Antwort @DianaR.
Narendrasingh Sisodia


So aktivieren Sie die Protokollierung von Eloquent "NameController :: create ();" Aussage?
Rubén Ruíz

2
Beachten Sie, dass in Laravel 5.4 die DB::listenRückruffunktion eine andere Signatur hat. Es ist eher so: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
racl101

45

Wenn Sie sich nur um die eigentliche Abfrage (die letzte Ausführung) für schnelle Debugging-Zwecke kümmern:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

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

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

Führen Sie ein Ein print_r()aus $laQuery[0], um die vollständige Abfrage einschließlich der Bindungen abzurufen. (Bei der $lcWhatYouWantobigen Variablen werden die Variablen durch ersetzt. ??)

Wenn Sie etwas anderes als die Haupt-MySQL-Verbindung verwenden, müssen Sie stattdessen diese verwenden:

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

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

(mit Ihrem Verbindungsnamen, wobei "mysql2" ist)


1
Wohin geht dieser Code? (5.4) Ich habe versucht, Controller, Modell und Middleware zu suchen, nicht sicher, wo ich es ausführen soll, bevor ich den DB-Fehler erhalte.
Blamb

Wenn beim Ausführen der Abfrage, die die Ausführung stoppt, eine Fehlermeldung angezeigt wird, sollte der Fehler das Problem anzeigen. Wenn Sie Fehler deaktiviert haben, können Sie das Fehlerprotokoll in / storage / log / laravel oder ähnliches überprüfen. (Ich bin momentan nicht an meinem Computer.) Wenn Sie sagen, dass beim Ausführen des in meiner Antwort vorgeschlagenen Codes eine Fehlermeldung angezeigt wird, stellen Sie sicher, dass Sie die DB-Fassade überall dort einschließen, wo Sie den Code ausführen. Sie sind sich nicht sicher, was Sie versuchen, aber der Controller scheint die korrekteste der von Ihnen genannten Optionen zu sein. (Ich führe normalerweise Abfragen in separaten Hilfsklassen aus)
Skeets

14

Fügen Sie dies in die Datei route.php ein:

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

Eingereicht von msurguy, Quellcode auf dieser Seite . Diesen Fixcode für Laravel 5.2 finden Sie in den Kommentaren.


Ein bisschen schmutzig, aber +1 für die $ query-> bindings und $ query-> time hints
Paolo Stefan

Ordentlich! Wenn Sie dies verwenden, werden die Ergebnisse in der Ansicht genau dort angezeigt, wo die Abfrage ausgeführt wird!
Charles Wood

14

Sie müssen zuerst die Abfrageprotokollierung aktivieren

DB::enableQueryLog();

Dann können Sie Abfrageprotokolle erhalten, indem Sie einfach:

dd(DB::getQueryLog());

Es ist besser, wenn Sie die Abfrageprotokollierung aktivieren, bevor die Anwendung gestartet wird. Dies können Sie in einer BeforeMiddleware tun und dann die ausgeführten Abfragen in AfterMiddleware abrufen.


11

Anscheinend DB::listenerhält der Abschluss in Laravel 5.2 nur einen einzigen Parameter.

Wenn Sie also DB::listenLaravel 5.2 verwenden möchten , sollten Sie Folgendes tun:

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

Für ältere Laravel habe ich meine Lösung zu stackoverflow.com/a/44920198/3823826
Csongor Halmai


5

Verwenden Sie toSql()statt get()wie folgt:

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

2

(Laravel 5.2) Ich finde, der einfachste Weg ist, nur eine Codezeile hinzuzufügen, um die SQL-Abfragen zu überwachen:

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

1

In Fortsetzung von Anscheinend mit Laravel 5.2 erhält der Abschluss in DB :: listen nur einen einzigen Parameter ... Antwort oben: Sie können diesen Code in das Middleware-Skript einfügen und in den Routen verwenden.

Zusätzlich:

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

Welcher Teil sollte in die Middleware gestellt werden? welche in Routen?
user1016265

1

Dieser Code ist für:

  • Laravel 5.2
  • Protokollieren Sie die Anweisungen in der MySQL-Datenbank

Hier ist der Code, der auf der Antwort von @milz basiert:

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

Der Kern ist die if(stripos...Zeile, die die Rekursion des Einfügens der insert into logSQL-Anweisung in die Datenbank verhindert.


0

Ich denke, die Antwort befindet sich in diesem Artikel: https://arjunphp.com/laravel-5-5-log-eloquent-queries/

ist schnell und einfach, um die Abfrageprotokollierung zu erreichen.

Sie müssen AppServiceProviderder bootMethode nur einen Rückruf hinzufügen , um DB-Abfragen abzuhören:

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

Angenommen, Sie möchten die SQL-Abfrage der folgenden Anweisungen drucken.

$user = User::find(5);

Sie müssen nur Folgendes tun:

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

$user = User::find(5);

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

Dadurch wird die zuletzt ausgeführte Abfrage in Laravel gedruckt.


-3

Für Laravel 5 und höher reicht es nicht, nur DB :: getQueryLog () zu verwenden. Standardmäßig ist dies der Wert von

 protected $loggingQueries = false;

ändere es auf

protected $loggingQueries = true; 

in der folgenden Datei für die Protokollierungsabfrage.

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

Und dann können wir das verwenden, DB::getQueryLog()wo Sie die Abfrage drucken möchten.


1
Es ist eine schlechte Idee, vendorDateien zu bearbeiten . Sie müssen original aufbewahrt werden.
Shukshin.ivan

@ shukshin.ivan Ja, man darf keine Herstellerdateien bearbeiten, aber um die genaue Abfrage zu erhalten, haben wir diesen Code vorerst bearbeitet, dann können wir ihn zurück ändern.
Rupali Pemare
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.