Laravel 5'te Sorgu Nasıl Çalıştırılır? DB :: getQueryLog () Boş Dizi Döndürüyor


173

Bir sorgu için günlük görüntülemeye çalışıyorum, ama DB::getQueryLog()sadece boş bir dizi döndürüyor:

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

Sonuç

Array
(
)

Bu sorgunun günlüğünü nasıl görüntüleyebilirim?


Laravel Debugbar sorguları kaydetmek için harika bir araçtır. Ayrıca birçok harika özelliği var.
totymedli

Yanıtlar:


256

Varsayılan olarak, sorgu günlüğü Laravel 5'te devre dışı bırakılmıştır: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

Sorgu günlüğünü aşağıdakileri arayarak etkinleştirmeniz gerekir:

DB::enableQueryLog();

veya bir olay dinleyicisini kaydettirin:

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

Bazı ipuçları

1. Çoklu DB bağlantıları

Birden fazla DB bağlantınız varsa, hangi bağlantının günlüğe kaydedileceğini belirtmelisiniz

Sorgu günlüğünü etkinleştirmek için my_connection:

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

Şunun için sorgu günlüğünü almak için my_connection:

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

2. Sorgu günlüğü nerede etkinleştirilir?

Bir HTTP isteği yaşam döngüsü için, handlebazı BeforeAnyDbQueryMiddleware ara katman yazılımının yönteminde sorgu günlüğünü etkinleştirebilir ve daha sonra terminateaynı ara katman yazılımının yönteminde yürütülen sorguları alabilirsiniz .

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

Bir ara yazılım zinciri esnaf komutları için çalışmaz, bu nedenle CLI yürütmesi için artisan.startolay dinleyicisinde sorgu günlüğünü etkinleştirebilirsiniz .

Örneğin, bootstrap/app.phpdosyaya koyabilirsiniz

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

3. Bellek

Laravel tüm sorguları hafızada tutar. Bu nedenle, çok sayıda satır eklerken veya çok fazla sorguyla uzun süren bir işte çalışırken, bu durum uygulamanın fazla bellek kullanmasına neden olabilir.

Çoğu durumda sorgu günlüğüne yalnızca hata ayıklama için ihtiyacınız olacaktır ve bu durumda yalnızca geliştirme için etkinleştirmenizi öneririm.

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

Referanslar


6
Sisteminiz birden fazla db bağlantısı kullanıyorsa, bunu belirtmeniz gerekir, aksi takdirde boş dizi döndürebilir:\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
Diana R.

Yorumunuzu yanıt olarak gönderin @ DianaR.
Narendrasingh Sisodia


Eloquent "NameController :: create ();" Beyan?
Rubén Ruíz

2
Laravel 5.4'te DB::listengeri arama işlevinin farklı bir imzası olduğunu unutmayın. Daha çok şöyle: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
racl101

45

Gerçekten önemsediğiniz tek şey, hızlı hata ayıklama amacıyla asıl sorgu (son çalışma) ise:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

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

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

bağlamalar dahil tam sorguyu almak için bir print_r()açık $laQuery[0]yapın. ( $lcWhatYouWantyukarıdaki değişkenin yerine değişkenler gelir ??)

Ana mysql bağlantısı dışında bir şey kullanıyorsanız, bunun yerine bunları kullanmanız gerekir:

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

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

("mysql2" nin bulunduğu bağlantı adınızla)


1
bu kod nereye gidiyor? (5.4) Denetleyici, model denedim ve ara katman yazılımına baktım, db hatasını almadan önce nerede çalıştırılacağından emin değilim.
blamb

Yürütmeyi durduran sorguyu çalıştırırken bir hata alıyorsanız, hata size sorunun ne olduğunu bildirmelidir. Kapatılmış hatalarınız varsa, / storage / log / laravel hata girişini veya bunun gibi bir şeyi kontrol edebilirsiniz. (Şu anda bilgisayarımda değilim) Cevabımda önerdiğim kodu çalıştırırken bir hata alıyorsanız, kodu çalıştırdığınız yere DB cephesini eklediğinizden emin olun. Ne yapmaya çalıştığınızdan emin değilsiniz, ancak denetleyici, bahsettiğiniz seçeneklerden en doğru gibi görünüyor. (Genellikle ayrı yardımcı sınıflarda sorgular çalıştırırım)
Skeets

15

İlk olarak sorgu günlüğünü etkinleştirmeniz gerekir

DB::enableQueryLog();

Sonra basitçe sorgu günlükleri alabilirsiniz:

dd(DB::getQueryLog());

Uygulama başlamadan önce sorgu günlüğünü etkinleştirirseniz, bir BeforeMiddleware içinde yapabilir ve sonra AfterMiddleware'de yürütülen sorguları alabilirsiniz.


14

Bunu route.php dosyasına koyun:

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

Bu sayfadaki kaynak kodu msurguy tarafından sunulmuştur . Laravel 5.2 için bu düzeltme kodunu yorumlarda bulabilirsiniz.


Biraz kirli, ama $ query-> bağlamaları ve $ query-> zaman ipuçları için +1
Paolo Stefan

Temiz! Bunu kullanmak, görünümde, sorgunun gerçekleştiği yerde sonuçları gösterir!
Charles Wood

11

Görünüşe göre Laravel 5.2 ile, kapak DB::listensadece tek bir parametre alıyor.

Yani, DB::listenLaravel 5.2'de kullanmak istiyorsanız , şöyle bir şey yapmalısınız:

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

Eski Laravel için çözümümü stackoverflow.com/a/44920198/3823826
Csongor Halmai


5

toSql()Bunun yerine kullanın get():

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

2

(Laravel 5.2) Ben basit yolu sadece sql sorguları izlemek için bir kod satırı eklemek olduğunu bulmak:

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

1

Görünüşe göre Laravel 5.2 ile devam ederken, DB :: listen'deki kapatma sadece tek bir parametre ... yukarıdaki yanıtı alır: bu kodu Middleware betiğine koyabilir ve yollarda kullanabilirsiniz.

Bunlara ek olarak:

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

hangi kısım ara katman yazılımına yerleştirilmelidir? hangi rotalarda?
user1016265

1

Bu kod:

  • Laravel 5.2
  • İfadeleri mysql veritabanına kaydedin

İşte milz'in cevabına dayanan kod:

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

Çekirdek, sql deyimini veritabanına if(stripos...eklemenin tekrarlanmasını önleyen çizgidir insert into log.


0

Bence bu makalede verilen cevap: https://arjunphp.com/laravel-5-5-log-eloquent-queries/

sorgu günlüğü elde etmek için hızlı ve basittir.

Sadece eklemek zorunda AppServiceProvideriçinde bootDB sorguları dinlemek için yöntemin bir geri arama:

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

Aşağıdaki ifadelerin SQL sorgusunu yazdırmak istediğinizi varsayalım.

$user = User::find(5);

Sadece aşağıdaki gibi yapmanız gerekir:

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

$user = User::find(5);

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

Bu, Laravel'de son yürütülen sorguyu yazdırır.


-3

Sadece DB :: getQueryLog () kullanarak laravel 5 ve sonrası için, yapmaz. Bu varsayılan: tarafından

 protected $loggingQueries = false;

olarak değiştir

protected $loggingQueries = true; 

günlük kaydı sorgusu.

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

Ve sonra DB::getQueryLog()sorguyu yazdırmak istediğiniz yeri kullanabiliriz .


1
vendorDosyaları düzenlemek kötü bir fikirdir . Orijinal olarak saklanmalıdır.
shukshin.ivan

@ shukshin.ivan Evet, satıcı dosyalarını düzenlememeliyiz, ancak kesin sorguyu elde etmek için şimdilik bu kodu düzenledik ve geri değiştirebiliriz.
Rupali Pemare
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.