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?

Arsen
fonte
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

Marty Aghajanyan
fonte
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
1
Para o Laravel 5.2, consulte: laravel.com/docs/5.2/database#listening-for-query-events
Dmitri Chebotarev
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á)

Skeets
fonte
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.

Rubén Ruíz
fonte
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.

Vineet Garg
fonte
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);
    }
);
Luís Cruz
fonte
Para Laravel mais velho, eu adicionei a minha solução para stackoverflow.com/a/44920198/3823826
Csongor Halmai
8

Para o laravel 5.8, basta adicionar dd ou dump .

Ex:

DB::table('users')->where('votes', '>', 100)->dd();

ou

DB::table('users')->where('votes', '>', 100)->dump();

referência: https://laravel.com/docs/5.8/queries#debugging

larp
fonte
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'
doncadavona
fonte
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); });
ChrisH
fonte
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);
Pai Santo
fonte
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.

ch271828n
fonte
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));
        });
    }
}
Javier Núñez
fonte
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.

Gufran Hasan
fonte
-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.

Rupali Pemare
fonte
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