Debugger les requêtes SQL dans Laravel

Publié le 27 juin 2022 par Mathieu De Gracia
Mis à jour le 6 mars 2024
Couverture de l'article Debugger les requêtes SQL dans Laravel

Ce tuto se base sur un Laravel 9.18

Vous exécutez probablement quotidiennement des requêtes SQL dans votre application Laravel que ce soit depuis Eloquent ou bien le Query Builder.

Mais que faire si vous êtes amené à debugger ces requêtes ? Comment visualiser la query, vérifier les arguments, le temps d'exécution ...

Nous allons voir dans cet article les différentes options qui s'offrent à nous afin de débugger efficacement nos requêtes dans votre application Laravel !

  1. toSql & getBindings
  2. dd & dump
  3. Query Logs
  4. Listen
  5. Ray
  6. When Querying For Longer Than

toSql & getBindings

Probablement les plus vieilles méthodes de cet article, les méthodes toSql et getBindings datent de l'époque de Laravel 4.

La premiere, une fois ajoutée à votre requête affichera la query sous la forme d'un string sans l'exécuter.

1$dump = User::where('name', 'Taylor')->toSql();
2 
3echo $dump;
4 
5# "select * from `users` where `name` = ?"

Tandis que la seconde affichera dans un array les bindings de votre requête.

1$dump = User::where('name', 'Taylor')->getBindings();
2 
3dd($dump);
4 
5# array:1 [
6# 0 => "Taylor"
7# ]

Une association des deux comportements, requête et binding, est possible grâce à la méthode toRawSql :

1$dump = User::where('name', 'Taylor')->toRawSql();
2 
3dd($dump);
4 
5# select * from "users" where "name" = 'Taylor'

Une façon plus concise d'obtenir ce résultat consistera à utiliser la méthode ddRawSql :

1User::where('name', 'Taylor')->ddRawSql();
2 
3# select * from "users" where "name" = 'Taylor'

dd & dump

La méthode dd combine nos deux précédentes méthodes en une, elle retournera dans un array la requête ainsi que les bindings sans l'exécuter.

1User::where('name', 'Taylor')->dd();
2 
3# "select * from "users" where "name" = ?"
4#
5# array:1 [
6# 0 => "Taylor"
7# ]

La méthode dump diffère quelque peu de dd en retournant une instance de Builder vous permettant d'exécuter dans un second temps la requête !

1$builder = User::where('name', 'Taylor')->dump();
2 
3# array:1 [
4# 0 => "Taylor"
5#]
6 
7$user = $builder->first();
8 
9dd($user);
10 
11# {#2713
12# +"id": 1
13# +"name": "Taylor"
14# }

Dans cet exemple, la query, les bindings ainsi que le résultat du first() s'afficheront sur votre écran.

Query logs

Toutes les méthodes que nous venons de voir étaient pratiques mais relativement intrusives vous obligeant à placer judicieusement les dumps dans vos requêtes.

Mais comment faire pour log plusieurs requêtes successives ?

Pour répondre à cette problématique la façade DB de Laravel propose une méthode enableQueryLog enregistrant toutes les requêtes suivant son utilisation.

1use Illuminate\Support\Facades\DB;
2 
3DB::connection()->enableQueryLog();
4 
5User::where('name', 'Taylor')->get();
6User::where('name', 'Abigail')->get();
7 
8$queries = DB::getQueryLog();
9 
10dd($queries);

Une fois vos requêtes exécutées, cette même façade DB dispose d'une méthode getQueryLog récupérant les logs sour la forme d'un tableau associatif.

1^ array:1 [▼
2 0 => array:3 [▼
3 "query" => "select * from `users` where `name` = ?"
4 "bindings" => array:1 [▼
5 0 => "Taylor"
6 ]
7 "time" => 33.1
8 ]
9 ...
10]

Listen

Dernière possibilité offerte par Laravel, la façade DB dispose d'un observer listen attrapant toutes les requêtes que votre application exécute.

Une fois placé judicieusement dans le boot d'un ServiceProvider cette méthode sera la moins intrusive de toutes.

1use Illuminate\Support\Facades\DB;
2 
3DB::listen(function($query) {
4 /* Illuminate\Database\Events\QueryExecuted */
5 dd($query);
6});

Dans cette closure, la variable $query est une instance de QueryExecuted correspondant à la requête dernièrement exécutée et contenant plusieurs propriétés publiques.

1$query->sql;
2$query->bindings;
3$query->time;

Ray

Ray est un logiciel open source cherchant à améliorer notre expérience de debug, il fonctionne sur bon nombre de système (PHP, Vue, Javascript ...) mais une attention particulière fut portée sur Laravel.

Ray est un logiciel payant, une offre trial est disponible pour tester l'outil.

Le logiciel permet de debug en live vos applications, d'ajouter une multitude de breakpoints semblables à l'utilisation de xdebug ainsi que de visualiser les performances de vos requêtes SQL !

Après avoir installé le logiciel et ajouté cette dépendance à votre projet :

1composer require spatie/laravel-ray --dev

Vous n'avez plus qu'à activer le log des requêtes avec la méthode showQueries().

1ray()->showQueries();

D'une façon semblable au listen que nous avons vu précédemment le boot d'un ServiceProvider sera un lieu judicieux pour accueillir cette méthode.

Désormais toutes les requêtes que le framework exécute arriveront dans le logiciel !

Utilisateurs de docker, une configuration spécifique est requise.

When Querying For Longer Than

Toute nouvelle méthode qui fut incluse au framework durant l'écriture de cet article, whenQueryingForLongerThan est désormais disponible à partir d'un Laravel 9.18.

Contrairement aux précédentes méthodes que nous venons de voir, cette dernière ne permet pas de debugger à proprement parler mais d'exécuter une closure quand une requête dépasse un certain temps d'execution.

1use Illuminate\Support\Facades\DB;
2use Illuminate\Database\Connection;
3 
4DB::whenQueryingForLongerThan($milliseconds = 500, function (Connection $connection) {
5 /* Illuminate\Database\Connection */
6 $connection;
7});
Mathieu De Gracia avatar
Mathieu De Gracia
Des fois, mon chat code à ma place 🐱

A lire

Autres articles de la même catégorie