J'essaie d'afficher le journal d'une requête, mais DB::getQueryLog()
renvoie simplement un tableau vide:
$user = User::find(5);
print_r(DB::getQueryLog());
Résultat
Array
(
)
Comment afficher le journal de cette requête?
Par défaut, le journal de requête est désactivé dans Laravel 5: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448
Vous devrez activer le journal des requêtes en appelant:
DB::enableQueryLog();
ou enregistrer un auditeur d'événement:
DB::listen(
function ($sql, $bindings, $time) {
// $sql - select * from `ncv_users` where `ncv_users`.`id` = ? limit 1
// $bindings - [5]
// $time(in milliseconds) - 0.38
}
);
Si vous avez plusieurs connexions à la base de données, vous devez spécifier la connexion à enregistrer.
Pour activer le journal de requête pour my_connection
:
DB::connection('my_connection')->enableQueryLog();
Pour obtenir le journal de requête pour my_connection
:
print_r(
DB::connection('my_connection')->getQueryLog()
);
Pour un cycle de vie de requête HTTP, vous pouvez activer le journal des requêtes dans la méthode handle
de certains BeforeAnyDbQueryMiddleware
middleware , puis récupérer les requêtes exécutées dans la méthode terminate
du même 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 chaîne d'un middleware ne s'exécutera pas pour les commandes artisanales. Par conséquent, pour l'exécution de la CLI, vous pouvez activer le journal des requêtes dans l'écouteur d'événements artisan.start
.
Par exemple, vous pouvez le mettre dans le fichier bootstrap/app.php
$app['events']->listen('artisan.start', function(){
\DB::enableQueryLog();
});
Laravel garde toutes les requêtes en mémoire. Ainsi, dans certains cas, par exemple lors de l'insertion d'un grand nombre de lignes ou d'un travail long avec beaucoup de requêtes, l'application peut utiliser trop de mémoire.
Dans la plupart des cas, vous aurez besoin du journal de requête uniquement pour le débogage. Si tel est le cas, je vous recommanderais de l'activer uniquement pour le développement.
if (App::environment('local')) {
// The environment is local
DB::enableQueryLog();
}
Références
Apparemment avec Laravel 5.2, la fermeture dans DB::listen
ne reçoit qu'un seul paramètre.
Donc, si vous voulez utiliser DB::listen
dans Laravel 5.2, vous devriez faire quelque chose comme:
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);
}
);
Mettez ceci sur le fichier 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>';
});
Soumis par msurguy, code source dans cette page . Vous trouverez ce code de correction pour laravel 5.2 dans les commentaires.
Pour laravel 5.8 vous venez d'ajouter jj ou déverser.
Ex:
DB::table('users')->where('votes', '>', 100)->dd();
ou
DB::table('users')->where('votes', '>', 100)->dump();
(Laravel 5.2) Le moyen le plus simple consiste à ajouter une ligne de code pour surveiller les requêtes SQL: \DB::listen(function($sql) {var_dump($sql); });
Ce code est pour:
Voici le code, basé sur la réponse 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();
}
});
Le noyau est la ligne if(stripos...
, ce qui empêche la récursivité d'insérer l'instruction insert into log
sql dans la base de données.
En continuant le Apparemment avec Laravel 5.2, la fermeture dans DB :: listen ne reçoit qu'un seul paramètre ... réponse ci-dessus: vous pouvez mettre ce code dans le script Middleware et l'utiliser dans les routes.
Aditionellement:
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);
Utilisez toSql()
au lieu de get()
comme suit:
$users = User::orderBy('name', 'asc')->toSql();
echo $users;
\\ Outputs the string:
'select * from `users` order by `name` asc'