Bagaimana cara agar kueri dieksekusi di Laravel 5? DB :: getQueryLog () Mengembalikan Array Kosong


173

Saya mencoba melihat log untuk kueri, tetapi DB::getQueryLog()hanya mengembalikan array kosong:

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

Hasil

Array
(
)

Bagaimana saya bisa melihat log untuk kueri ini?


Laravel Debugbar adalah alat yang hebat untuk mencatat kueri. Ini juga memiliki banyak fitur luar biasa lainnya.
totymedli

Jawaban:


256

Secara default, log kueri dinonaktifkan di Laravel 5: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

Anda harus mengaktifkan log kueri dengan menelepon:

DB::enableQueryLog();

atau daftarkan pendengar acara:

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

Beberapa tips

1. Banyak koneksi DB

Jika Anda memiliki lebih dari satu koneksi DB, Anda harus menentukan koneksi mana yang akan dicatat

Untuk mengaktifkan log kueri untuk my_connection:

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

Untuk mendapatkan log permintaan untuk my_connection:

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

2. Di mana harus mengaktifkan log kueri?

Untuk siklus permintaan HTTP, Anda dapat mengaktifkan log kueri dalam handlemetode beberapa BeforeAnyDbQueryMiddleware middleware dan kemudian mengambil kueri yang dieksekusi dalam terminatemetode middleware yang sama.

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

Rantai middleware tidak akan berjalan untuk perintah artisan, jadi untuk eksekusi CLI Anda dapat mengaktifkan log kueri di artisan.startpendengar acara.

Misalnya Anda bisa memasukkannya ke dalam bootstrap/app.phpfile

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

3. Memori

Laravel menyimpan semua pertanyaan dalam memori. Jadi dalam beberapa kasus, seperti saat memasukkan banyak baris, atau memiliki pekerjaan yang berjalan lama dengan banyak pertanyaan, ini dapat menyebabkan aplikasi menggunakan memori berlebih.

Dalam kebanyakan kasus, Anda akan memerlukan log kueri hanya untuk debugging, dan jika itu yang saya sarankan Anda mengaktifkannya hanya untuk pengembangan.

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

Referensi


6
Jika sistem Anda menggunakan lebih dari satu koneksi db, Anda harus menentukannya, jika tidak maka akan mengembalikan array kosong:\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
Diana R.

Posting komentar Anda sebagai jawaban Anda @DianaR.
Narendrasingh Sisodia


Cara mengaktifkannya untuk masuk Eloquent "NameController :: create ();" pernyataan?
Rubén Ruíz

2
Perhatikan bahwa dalam Laravel 5.4 DB::listenfungsi panggilan balik memiliki tanda tangan yang berbeda. Ini lebih seperti ini: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
racl101

45

Jika yang Anda benar-benar pedulikan adalah permintaan aktual (yang terakhir kali dijalankan) untuk keperluan debugging cepat:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

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

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

lakukan print_r()on $laQuery[0]untuk mendapatkan permintaan penuh, termasuk binding. ( $lcWhatYouWantvariabel di atas akan diganti dengan variabel ??)

Jika Anda menggunakan sesuatu selain koneksi mysql utama, Anda harus menggunakan ini sebagai gantinya:

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

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

(dengan nama koneksi Anda di mana "mysql2" berada)


1
kemana kode ini pergi? (5.4) Saya sudah mencoba controller, model, dan mencari di middleware, tidak yakin di mana harus menjalankannya sebelum saya mendapatkan kesalahan db.
blamb

Jika Anda mendapatkan kesalahan saat menjalankan kueri yang menghentikan eksekusi, kesalahan tersebut harus memberi tahu Anda apa masalahnya. Jika Anda memiliki kesalahan dimatikan, Anda dapat memeriksa log kesalahan di / storage / log / laravel atau sesuatu seperti itu. (Saya tidak ada di komputer saya saat ini) Jika Anda mengatakan Anda mendapatkan kesalahan dalam menjalankan kode yang saya sarankan dalam jawaban saya, pastikan Anda menyertakan fasad DB di mana pun Anda menjalankan kode. Tidak yakin apa yang Anda coba lakukan, tetapi pengontrol terdengar seperti yang paling benar dari opsi yang Anda sebutkan. (Saya biasanya menjalankan query dalam kelas pembantu terpisah)
Skeets

15

Anda harus terlebih dahulu mengaktifkan pencatatan permintaan

DB::enableQueryLog();

Kemudian Anda bisa mendapatkan log kueri hanya dengan:

dd(DB::getQueryLog());

Akan lebih baik jika Anda mengaktifkan pencatatan log sebelum aplikasi dimulai, yang dapat Anda lakukan di BeforeMiddleware dan kemudian mengambil kueri yang dieksekusi di AfterMiddleware.


14

Letakkan ini di file 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>';
});

Dikirim oleh msurguy, kode sumber di halaman ini . Anda akan menemukan kode perbaikan ini untuk laravel 5.2 dalam komentar.


Agak kotor, tapi +1 untuk $ query-> binding dan $ query-> petunjuk waktu
Paolo Stefan

Rapi! Menggunakan ini menunjukkan hasil dalam tampilan, tepat di tempat permintaan itu terjadi!
Charles Wood

11

Rupanya dengan Laravel 5.2, penutupan DB::listenhanya menerima parameter tunggal.

Jadi, jika Anda ingin menggunakan DB::listenLaravel 5.2, Anda harus melakukan sesuatu seperti:

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

Untuk Laravel yang lebih tua, saya menambahkan solusi saya ke stackoverflow.com/a/44920198/3823826
Csongor Halmai


5

Gunakan toSql()bukannya get()seperti itu:

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

2

(Laravel 5.2) Saya menemukan cara paling sederhana adalah dengan menambahkan satu baris kode untuk memantau kueri sql:

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

1

Dalam melanjutkan Rupanya dengan Laravel 5.2, penutupan di DB :: listen hanya menerima parameter tunggal ... respons di atas: Anda dapat memasukkan kode ini ke dalam skrip Middleware dan menggunakannya dalam rute.

Selain itu:

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

bagian mana yang harus ditempatkan ke middleware? rute mana?
user1016265

1

Kode ini untuk:

  • Laravel 5.2
  • Log pernyataan ke dalam database mysql

Ini adalah kode yang didasarkan pada jawaban @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();
        }
    });

Inti adalah if(stripos...garis, yang mencegah rekursi memasukkan insert into logpernyataan sql ke dalam basis data.


0

Saya pikir jawabannya ada di artikel ini: https://arjunphp.com/laravel-5-5-log-eloquent-queries/

cepat dan mudah untuk mencapai pencatatan permintaan.

Anda hanya perlu menambahkan ke AppServiceProviderdalam bootmetode panggilan balik untuk mendengarkan pertanyaan 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

Misalkan Anda ingin mencetak query SQL dari pernyataan berikut.

$user = User::find(5);

Anda hanya perlu melakukan hal berikut:

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

$user = User::find(5);

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

Ini akan mencetak kueri yang terakhir dieksekusi di Laravel.


-3

Untuk laravel 5 dan seterusnya hanya menggunakan DB :: getQueryLog (), tidak akan dilakukan. Secara default dalam hal ini nilai

 protected $loggingQueries = false;

ubah ke

protected $loggingQueries = true; 

dalam file di bawah ini untuk kueri logging.

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

Dan kemudian kita bisa menggunakan DB::getQueryLog()tempat Anda ingin mencetak kueri.


1
Itu ide yang buruk, untuk mengedit vendorfile. Mereka harus tetap asli.
shukshin.ivan

@ shukshin.ivan Ya kita tidak boleh mengedit file vendor tetapi untuk mendapatkan permintaan yang tepat kita telah mengedit kode ini untuk sementara waktu maka kita dapat mengubahnya kembali.
Rupali Pemare
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.