La méthode HTTP QUERY, définie dans la RFC 10008, est une méthode de requête sûre et cacheable qui porte les paramètres de requête dans le corps plutôt que dans l'URL. Elle offre l'expressivité d'un payload POST tout en conservant la sémantique en lecture seule de GET. Laravel 13.19 a ajouté Http::query() au client HTTP et le helper de test queryJson(); Laravel 14 proposera un helper Route::query() de première classe, mais d'ici là Route::match(['QUERY'], ...) fonctionne déjà.
Le tutoriel part d'une application Laravel 13 fraîche, installe le fichier de routes API et Scout, puis configure le driver database dans .env pour que Scout effectue des requêtes WHERE LIKE sur la base existante. Il crée un modèle Article avec migration et factory, ajoute le trait Searchable et surcharge toSearchableArray() pour n'exposer que les colonnes title et body.
La route est enregistrée dans routes/api.php avec Route::match(['QUERY'], '/articles/search', ...) et un closure qui valide search comme chaîne obligatoire et per_page comme entier optionnel entre 1 et 50. Elle appelle ensuite Article::search($validated['search'])->paginate($validated['per_page'] ?? 15). Parce que QUERY est traitée comme POST pour la lecture des entrées, $request->input() et la validation lisent directement le corps JSON. php artisan route:list affiche QUERY api/articles/search; un client envoie un corps JSON comme {"search": "scout", "per_page": 10}.
Les tests utilisent le helper queryJson() introduit dans Laravel 13.19; un exemple emploie RefreshDatabase, des factories pour peupler la base, et vérifie que le endpoint retourne l'article correspondant et valide le paramètre search. Côté consommateur, le client HTTP Laravel peut appeler le endpoint avec Http::acceptJson()->query('https://example.com/api/articles/search', ['search' => 'scout']).
Un piège pratique : le serveur de développement intégré de PHP rejette la méthode QUERY avec une réponse 501 avant que Laravel ne la voie, donc php artisan serve ne convient pas. Les environnements basés sur Nginx comme Laravel Herd et Valet laissent passer le verbe. Les helpers de test HTTP de Laravel évitent ce problème en routant la requête directement dans le framework.
Si la route est placée dans routes/web.php, le middleware PreventRequestForgery de Laravel 13 exigera un token CSRF, car il ne considère comme méthodes de lecture que HEAD, GET et OPTIONS. En attendant que Laravel 14 exempte QUERY par défaut, le tutoriel propose deux solutions. La première consiste à étendre PreventRequestForgery, surcharger isReading() pour inclure QUERY, et remplacer le middleware de base dans le groupe web via bootstrap/app.php. La seconde consiste à appliquer withoutMiddleware(PreventRequestForgery::class) sur une seule route QUERY. L'article recommande la première, car elle disparaît proprement lors de la montée de version. Les tests ne déclencheront pas l'erreur 419 tant que l'environnement est testing, car le middleware CSRF saute la vérification dans cet environnement. Dans tous les cas, les gestionnaires QUERY doivent rester en lecture seule, comme les gestionnaires GET.
Avant la mise en production, l'article met en garde : le framework n'est qu'un maillon de la chaîne. Les CDN, WAF, load balancers ou proxies peuvent bloquer un verbe inconnu. Les navigateurs supportent fetch() avec QUERY, mais pas les formulaires HTML; QUERY n'est pas une méthode CORS safelisted, donc les requêtes cross-origin déclencheront un preflight. Bien que QUERY soit définie comme cacheable, navigateurs et CDN ne l'implémentent pas encore. OpenAPI n'a ajouté une opération query native qu'en version 3.2, publiée en septembre 2025, donc les générateurs et SDK anciens peuvent ne pas la décrire. Un API interne où l'on contrôle les deux extrémités est le meilleur endroit pour expérimenter.
À la sortie de Laravel 14, Route::match(['QUERY'], ...) pourra être remplacé par Route::query(...), et la surcharge du middleware CSRF pourra être supprimée; le reste du code reste inchangé.