Come eseguire la query in Laravel 5? DB :: getQueryLog () Restituzione di array vuoti


173

Sto cercando di visualizzare il registro per una query, ma DB::getQueryLog()sta solo restituendo un array vuoto:

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

Risultato

Array
(
)

Come posso visualizzare il registro per questa query?


Laravel Debugbar è un ottimo strumento per registrare le query. Ha anche molte altre fantastiche funzionalità.
totymedli,

Risposte:


256

Per impostazione predefinita, il registro delle query è disabilitato in Laravel 5: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

Sarà necessario abilitare il registro delle query chiamando:

DB::enableQueryLog();

o registra un listener di eventi:

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

Alcuni suggerimenti

1. Più connessioni DB

Se si dispone di più di una connessione DB, è necessario specificare quale connessione registrare

Per abilitare il registro delle query per my_connection:

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

Per ottenere il registro delle query per my_connection:

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

2. Dove abilitare il registro delle query?

Per un ciclo di vita delle richieste HTTP, è possibile abilitare il registro delle query nel handlemetodo di alcuni BeforeAnyDbQueryMiddleware middleware e quindi recuperare le query eseguite nelterminate metodo dello stesso middleware.

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

La catena di un middleware non verrà eseguita per comandi artigianali, quindi per l'esecuzione della CLI è possibile abilitare il registro delle query nel artisan.startlistener di eventi.

Ad esempio, puoi inserirlo nel bootstrap/app.phpfile

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

3. Memoria

Laravel mantiene tutte le domande in memoria. Pertanto, in alcuni casi, ad esempio quando si inserisce un numero elevato di righe o si esegue un processo di lunga durata con molte query, ciò può far sì che l'applicazione utilizzi memoria in eccesso.

Nella maggior parte dei casi è necessario il registro delle query solo per il debug e, in tal caso, consiglierei di abilitarlo solo per lo sviluppo.

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

Riferimenti


6
Se il tuo sistema utilizza più di una connessione db, devi specificarla, altrimenti potrebbe restituire un array vuoto:\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
Diana R.

Pubblica il tuo commento come risposta @DianaR.
Narendrasingh Sisodia,


Come abilitarlo per registrare Eloquent "NameController :: create ();" affermazione?
Rubén Ruíz,

2
Si noti che in Laravel 5.4 la DB::listenfunzione di callback ha una firma diversa. È più così: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
racl101,

45

Se tutto ciò che ti interessa è la query effettiva (l'ultima esecuzione) per scopi di debug rapido:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

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

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

fare un print_r()on $laQuery[0]per ottenere la query completa, inclusi i binding. (la $lcWhatYouWantvariabile sopra avrà le variabili sostituite con ??)

Se stai usando qualcosa di diverso dalla connessione mysql principale, dovrai invece utilizzare questi:

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

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

(con il nome della tua connessione dove si trova "mysql2")


1
dove va questo codice però? (5.4) Ho provato il controller, il modello e ho cercato nel middleware, non sono sicuro di dove eseguirlo prima di ottenere l'errore db.
blamb

Se viene visualizzato un errore durante l'esecuzione della query che interrompe l'esecuzione, l'errore dovrebbe indicare quale è il problema. Se hai errori disattivati, puoi controllare il log degli errori in / storage / log / laravel o qualcosa del genere. (Al momento non sono al mio computer) Se stai dicendo che stai ricevendo un errore durante l'esecuzione del codice che ho suggerito nella mia risposta, assicurati di includere la facciata DB ovunque tu stia eseguendo il codice. Non sei sicuro di cosa stai cercando di fare, ma il controller suona come la più corretta delle opzioni che hai citato. (Di solito eseguo query in classi di aiuto separate)
Skeets,

15

È necessario prima abilitare la registrazione delle query

DB::enableQueryLog();

Quindi puoi ottenere i log delle query semplicemente:

dd(DB::getQueryLog());

Sarebbe meglio se abiliti la registrazione delle query prima dell'avvio dell'applicazione, cosa che puoi fare in un BeforeMiddleware e poi recuperare le query eseguite in AfterMiddleware.


14

Metti questo sul file route.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>';
});

Inserito da msurguy, codice sorgente in questa pagina . Troverai questo codice di correzione per laravel 5.2 nei commenti.


Un po 'sporco, ma +1 per $ query-> associazioni e $ query-> suggerimenti temporali
Paolo Stefan

! Neat L'utilizzo di questo mostra i risultati nella vista, proprio dove si sta verificando la query!
Charles Wood,

11

Apparentemente con Laravel 5.2, la chiusura in DB::listenriceve solo un singolo parametro.

Quindi, se vuoi usare DB::listenin Laravel 5.2, dovresti fare qualcosa del tipo:

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

Per il vecchio Laravel, ho aggiunto la mia soluzione a stackoverflow.com/a/44920198/3823826
Csongor Halmai,


5

Usa toSql()invece di get()così:

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

2

(Laravel 5.2) Trovo che il modo più semplice sia solo quello di aggiungere una riga di codice per monitorare le query sql:

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

1

Nel proseguimento di Apparently with Laravel 5.2, la chiusura in DB :: Listen riceve solo un singolo parametro ... risposta sopra: è possibile inserire questo codice nello script Middleware e utilizzarlo nelle route.

Inoltre:

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

quale parte deve essere inserita nel middleware? quale nei percorsi?
user1016265,

1

Questo codice è per:

  • Laravel 5.2
  • Registra le istruzioni nel database mysql

Ecco il codice, che si basa sulla risposta di @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();
        }
    });

Il nucleo è la if(stripos...linea, che impedisce la ricorsione dell'inserimento insert into logdell'istruzione sql nel database.


0

Penso che la risposta si trovi in ​​questo articolo: https://arjunphp.com/laravel-5-5-log-eloquent-queries/

è rapido e semplice per ottenere la registrazione delle query.

Non vi resta che aggiungere al AppServiceProvidernel bootmetodo di un callback per ascoltare le query 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

Supponiamo di voler stampare la query SQL delle seguenti istruzioni.

$user = User::find(5);

Devi solo fare come segue:

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

$user = User::find(5);

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

Questo stamperà l'ultima query eseguita in Laravel.


-3

Per laravel 5 e successivi utilizzando solo DB :: getQueryLog (), non funzionerà. DA predefinito in questo il valore di

 protected $loggingQueries = false;

cambiarlo in

protected $loggingQueries = true; 

nel file seguente per la registrazione della query.

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

E quindi possiamo usare il punto in DB::getQueryLog()cui desideri stampare la query.


1
È una cattiva idea, modificare i vendorfile. Devono essere mantenuti originali.
shukshin.ivan,

@ shukshin.ivan Sì, non è necessario modificare i file del fornitore, ma per ottenere la query esatta abbiamo modificato questo codice per il momento, quindi possiamo cambiarlo nuovamente.
Rupali Pemare,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.