¿Cómo ejecutar la consulta en Laravel 5? DB :: getQueryLog () Devuelve una matriz vacía

173

Estoy tratando de ver el registro de una consulta, pero DB::getQueryLog()solo estoy devolviendo una matriz vacía:

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

Resultado

Array
(
)

¿Cómo puedo ver el registro de esta consulta?

Arsen
fuente
Laravel Debugbar es una gran herramienta para registrar las consultas. También tiene muchas otras características increíbles.
totymedli

Respuestas:

256

De manera predeterminada, el registro de consultas está deshabilitado en Laravel 5: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

Deberá habilitar el registro de consultas llamando a:

DB::enableQueryLog();

o registre un oyente de eventos:

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

Algunos consejos

1. Múltiples conexiones DB

Si tiene más de una conexión de base de datos, debe especificar qué conexión registrar

Para habilitar el registro de consultas para my_connection:

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

Para obtener el registro de consultas para my_connection:

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

2. ¿Dónde habilitar el registro de consultas?

Para un ciclo de vida de solicitud HTTP, puede habilitar el registro de consultas en el handlemétodo de algún BeforeAnyDbQueryMiddleware middleware y luego recuperar las consultas ejecutadas en el terminatemétodo del mismo 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 cadena de un middleware no se ejecutará para comandos artesanales, por lo que para la ejecución de CLI puede habilitar el registro de consultas en artisan.start detector de eventos.

Por ejemplo, puedes ponerlo en el bootstrap/app.phparchivo

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

3. Memoria

Laravel guarda todas las consultas en la memoria. Por lo tanto, en algunos casos, como cuando se inserta una gran cantidad de filas o se realiza un trabajo de larga duración con muchas consultas, esto puede hacer que la aplicación use un exceso de memoria.

En la mayoría de los casos, necesitará el registro de consultas solo para la depuración, y si ese es el caso, recomendaría que lo habilite solo para el desarrollo.

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

Referencias

Marty Aghajanyan
fuente
66
Si su sistema usa más de una conexión db, debe especificarla, de lo contrario podría devolver una matriz vacía:\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
Diana R.
Publique su comentario como su respuesta @DianaR.
Narendrasingh Sisodia
1
Para Laravel 5.2 ver: laravel.com/docs/5.2/database#listening-for-query-events
Dmitri Chebotarev
Cómo habilitarlo para registrar Eloquent "NameController :: create ();" ¿declaración?
Rubén Ruíz
2
Tenga en cuenta que en Laravel 5.4 la DB::listenfunción de devolución de llamada tiene una firma diferente. Es más así: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
racl101
45

Si todo lo que realmente le importa es la consulta real (la última ejecución) para fines de depuración rápida:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

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

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

haz un print_r()encendido $laQuery[0]para obtener la consulta completa, incluidos los enlaces. (la $lcWhatYouWantvariable anterior tendrá las variables reemplazadas por ??)

Si está usando algo diferente a la conexión principal de mysql, deberá usar estos en su lugar:

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

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

(con su nombre de conexión donde está "mysql2")

Esqueletos
fuente
1
¿A dónde va este código? (5.4) He probado el controlador, el modelo y busqué en el middleware, no estoy seguro de dónde ejecutarlo antes de obtener el error de db.
blamb
Si recibe un error al ejecutar la consulta que detiene la ejecución, el error debería indicarle cuál es el problema. Si tiene los errores desactivados, puede verificar el error de inicio de sesión / almacenamiento / registro / laravel o algo así. (No estoy en mi computadora en este momento) Si está diciendo que está recibiendo un error al ejecutar el código que sugerí en mi respuesta, asegúrese de incluir la fachada de la base de datos donde sea que esté ejecutando el código. No estoy seguro de lo que está tratando de hacer, pero el controlador parece la opción más correcta que mencionó. (Normalmente ejecuto consultas en clases de ayuda separadas)
Skeets
15

Primero debe habilitar el registro de consultas

DB::enableQueryLog();

Luego puede obtener registros de consultas simplemente:

dd(DB::getQueryLog());

Sería mejor si habilita el registro de consultas antes de que comience la aplicación, lo que puede hacer en un BeforeMiddleware y luego recuperar las consultas ejecutadas en AfterMiddleware.

Vineet Garg
fuente
14

Pon esto en el archivo 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 fuente en esta página . Encontrará este código de corrección para laravel 5.2 en los comentarios.

Rubén Ruíz
fuente
Un poco sucio, pero +1 para las consultas $ query-> bindings y $ query-> time
Paolo Stefan
¡Ordenado! ¡Usar esto muestra los resultados en la vista, justo donde está ocurriendo la consulta!
Charles Wood
11

Aparentemente con Laravel 5.2, el cierre DB::listensolo recibe un único parámetro.

Entonces, si desea usar DB::listenen Laravel 5.2, debe hacer 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
fuente
Para los antiguos Laravel, agregué mi solución a stackoverflow.com/a/44920198/3823826
Csongor Halmai el
5

Use en toSql()lugar de get()así:

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

(Laravel 5.2) Creo que la forma más simple es simplemente agregar una línea de código para monitorear las consultas sql:

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

Continuando con Aparentemente con Laravel 5.2, el cierre en DB :: listen solo recibe un solo parámetro ... respuesta anterior: puede poner este código en el script de Middleware y usarlo en las rutas.

Adicionalmente:

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);
Santo padre
fuente
¿Qué parte se debe colocar en el middleware? que en las rutas?
user1016265
1

Este código es para:

  • Laravel 5.2
  • Registre las declaraciones en la base de datos mysql

Aquí está el código, que se basa en la respuesta 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();
        }
    });

El núcleo es la if(stripos...línea, que evita la recurrencia de insertar la insert into loginstrucción sql en la base de datos.

ch271828n
fuente
0

Creo que la respuesta se encuentra en este artículo: https://arjunphp.com/laravel-5-5-log-eloquent-queries/

Es rápido y sencillo lograr el registro de consultas.

Sólo tienes que añadir a la AppServiceProviderdel bootmétodo de devolución de llamada para escuchar a las consultas de base de datos:

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
fuente
0

Suponga que desea imprimir la consulta SQL de las siguientes declaraciones.

$user = User::find(5);

Solo necesita hacer lo siguiente:

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

$user = User::find(5);

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

Esto imprimirá la última consulta ejecutada en Laravel.

Gufran Hasan
fuente
-3

Para laravel 5 y en adelante usando solo DB :: getQueryLog (), no funcionará. Por defecto en esto el valor de

 protected $loggingQueries = false;

cámbielo a

protected $loggingQueries = true; 

en el archivo a continuación para la consulta de registro.

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

Y luego podemos usar el lugar DB::getQueryLog()donde desea imprimir la consulta.

Rupali Pemare
fuente
1
Es una mala idea editar vendorarchivos. Deben mantenerse originales.
shukshin.ivan
@ shukshin.ivan Sí, uno no debe editar archivos de proveedores, pero para obtener la consulta exacta, hemos editado este código por el momento y luego podemos volver a cambiarlo.
Rupali Pemare