Como executar a consulta no Laravel 5? DB :: getQueryLog () retornando matriz vazia


171

Estou tentando visualizar o log para uma consulta, mas DB::getQueryLog()está retornando uma matriz vazia:

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

Resultado

Array
(
)

Como posso visualizar o log desta consulta?


O Laravel Debugbar é uma ótima ferramenta para registrar as consultas. Ele também tem muitos outros recursos impressionantes.
precisa saber é o seguinte

Respostas:


256

Por padrão, o log de consulta está desativado no Laravel 5: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

Você precisará habilitar o log de consulta chamando:

DB::enableQueryLog();

ou registre um ouvinte de evento:

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

Algumas dicas

1. Várias conexões de banco de dados

Se você tiver mais de uma conexão com o banco de dados, deverá especificar qual conexão registrar

Para habilitar o log de consulta para my_connection:

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

Para obter o log de consultas para my_connection:

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

2. Onde habilitar o log de consulta?

Para um ciclo de vida de solicitação HTTP, é possível ativar o log de consultas no handlemétodo de algum BeforeAnyDbQueryMiddleware middleware e, em seguida, recuperar as consultas executadas no terminatemétodo do mesmo 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()
        );
    }
}

A cadeia de um middleware não será executada para comandos artesanais; portanto, para a execução da CLI, você pode ativar o log de consulta no diretório artisan.start ouvinte de eventos.

Por exemplo, você pode colocá-lo no bootstrap/app.phparquivo

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

3. Memória

O Laravel mantém todas as consultas na memória. Portanto, em alguns casos, como ao inserir um grande número de linhas ou ter um trabalho de longa execução com muitas consultas, isso pode fazer com que o aplicativo use excesso de memória.

Na maioria dos casos, você precisará do log de consulta apenas para depuração e, se for esse o caso, recomendo que você o habilite apenas para desenvolvimento.

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

Referências


6
Se o seu sistema usa mais de uma conexão db, você tem que especificá-lo, caso contrário ele pode retornar array vazio:\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
Diana R.

Poste seu comentário como resposta @DianaR.
Narendrasingh Sisodia


Como habilitar o log do Eloquent "NameController :: create ();" declaração?
Rubén Ruíz 22/01

2
Observe que no Laravel 5.4 a DB::listenfunção de retorno de chamada possui uma assinatura diferente. É mais parecido com isto: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
racl101

45

Se você realmente se importa com a consulta real (a última executada) para fins de depuração rápida:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

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

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

fazer um print_r()on $laQuery[0]para obter a consulta completa, incluindo as ligações. (a $lcWhatYouWantvariável acima terá as variáveis ​​substituídas por?? )

Se você estiver usando algo diferente da conexão principal do mysql, precisará usá-los:

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

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

(com o nome da sua conexão onde "mysql2" está)


1
para onde esse código vai? (5.4) Eu tentei controlador, modelo e procurei no middleware, não sei onde executá-lo antes de receber o erro db.
blamb

Se você estiver recebendo um erro ao executar a consulta que está interrompendo a execução, o erro deve informar qual é o problema. Se você tiver erros desativados, poderá verificar o log de erros em / storage / log / laravel ou algo parecido. (Não estou no meu computador no momento) Se você está dizendo que está recebendo um erro ao executar o código que sugeri na minha resposta, inclua a fachada do banco de dados onde quer que esteja executando o código. Não tenho certeza do que você está tentando fazer, mas o controlador parece ser a mais correta das opções mencionadas. (Eu costumo executar consultas em classes auxiliares separadas)
Skeets

14

Coloque isso no arquivo 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>';
});

Enviado por msurguy, código-fonte nesta página . Você encontrará este código de correção para o laravel 5.2 nos comentários.


Um sujo pouco, mas +1 para os $ query-> ligações e US $ query-> dicas de tempo
Paolo Stefan

Arrumado! Usar isso mostra os resultados na exibição, exatamente onde a consulta está ocorrendo!
Charles Wood

14

Você precisa primeiro habilitar o log de consultas

DB::enableQueryLog();

Então você pode obter logs de consulta simplesmente:

dd(DB::getQueryLog());

Seria melhor se você habilitar o log de consultas antes do aplicativo iniciar, o que você pode fazer no BeforeMiddleware e recuperar as consultas executadas no AfterMiddleware.


11

Aparentemente, com o Laravel 5.2, o fechamento DB::listenrecebe apenas um único parâmetro.

Portanto, se você deseja usar DB::listenno Laravel 5.2, faça algo como:

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

Para Laravel mais velho, eu adicionei a minha solução para stackoverflow.com/a/44920198/3823826
Csongor Halmai


5

Use em toSql()vez de get():

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

2

(Laravel 5.2) Acho que a maneira mais simples é adicionar uma linha de código para monitorar as consultas sql:

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

1

Continuando o Aparentemente com o Laravel 5.2, o fechamento no DB :: listen recebe apenas um único parâmetro ... resposta acima: você pode colocar esse código no script Middleware e usá-lo nas rotas.

Além disso:

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

qual parte deve ser colocada no middleware? qual nas rotas?
user1016265

1

Este código é para:

  • Laravel 5.2
  • Registre as instruções no banco de dados mysql

Aqui está o código, que é baseado na resposta de @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();
        }
    });

O núcleo é a if(stripos...linha, que impede a recursão da inserção da insert into loginstrução sql no banco de dados.


0

Eu acho que a resposta localizada neste artigo: https://arjunphp.com/laravel-5-5-log-eloquent-queries/

é rápido e simples para obter o log de consultas.

Você apenas tem que adicionar ao AppServiceProviderno bootmétodo de uma chamada de retorno para ouvir consultas 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

Suponha que você deseje imprimir a consulta SQL das seguintes instruções.

$user = User::find(5);

Você só precisa fazer o seguinte:

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

$user = User::find(5);

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

Isso imprimirá a última consulta executada no Laravel.


-3

Para o laravel 5 em diante, usando apenas DB :: getQueryLog (), não funcionará. Por padrão, o valor de

 protected $loggingQueries = false;

mude para

protected $loggingQueries = true; 

no arquivo abaixo para registrar a consulta.

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

E então podemos usar o DB::getQueryLog()local em que você deseja imprimir a consulta.


1
É uma péssima ideia editar vendorarquivos. Eles devem ser mantidos originais.
Shukshin.ivan 2/17/17

@ shukshin.ivan Sim, não é necessário editar os arquivos do fornecedor, mas para obter a consulta exata, nós editamos este código por enquanto; podemos alterá-lo novamente.
Rupali Pemare
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.