Laravel Query Gate : APIs REST déclaratives (filtres, tris, actions, versioning)
DOG&DEV · 25/01/2025
Laravel Query Gate : APIs REST déclaratives (filtres, tris, actions, versioning)
Laravel Query Gate (behindsolution/laravel-query-gate) permet de générer des APIs REST (liste, show, create, update, delete) en les déclarant sur le modèle : filtres, tris, sélection de colonnes, actions personnalisées (publier, archiver, etc.) et versioning. Fini les contrôleurs répétitifs pour chaque ressource ; la doc OpenAPI peut être générée automatiquement.
Prérequis
- Laravel 10+ (ou 11/12)
- Modèles Eloquent avec relations si besoin de filtres imbriqués
1. Installation
composer require behindsolution/laravel-query-gate
Publier la config et enregistrer les modèles :
// config/query-gate.php
'models' => [
App\Models\Post::class,
App\Models\Comment::class,
],
2. Déclarer une Query Gate sur le modèle
Ajoutez le trait HasQueryGate et la méthode queryGate() :
use BehindSolution\LaravelQueryGate\Traits\HasQueryGate;
use BehindSolution\LaravelQueryGate\Support\QueryGate;
class Post extends Model
{
use HasQueryGate;
public static function queryGate(): QueryGate
{
return QueryGate::make()
->alias('posts')
->middleware(['auth:sanctum'])
->filters([
'status' => ['string', 'in:draft,published,archived'],
'category_id' => 'integer',
'author.name' => ['string', 'max:100'],
'created_at' => 'date',
])
->allowedFilters([
'status' => ['eq', 'in', 'neq'],
'category_id' => ['eq', 'in'],
'author.name' => ['like'],
'created_at' => ['gte', 'lte', 'between'],
])
->select(['id', 'title', 'slug', 'status', 'created_at', 'author.name'])
->sorts(['created_at', 'title'])
->actions(fn ($actions) => $actions
->create(fn ($a) => $a->validations([
'title' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]))
->update()
->delete()
);
}
}
Aucun contrôleur ni routes manuels pour le CRUD de base.
3. Routes générées
Pour l’alias posts :
- GET /query/posts — Liste (filtres, tri, pagination)
- GET /query/posts/{id} — Détail
- POST /query/posts — Création
- PATCH /query/posts/{id} — Mise à jour
- DELETE /query/posts/{id} — Suppression
Le préfixe (/query) et le middleware sont configurables.
4. Filtres et notation pointée
Exemples de requêtes :
GET /query/posts?filter[status][eq]=published
GET /query/posts?filter[category_id][in]=1,2,3
GET /query/posts?filter[author.name][like]=John
GET /query/posts?filter[created_at][between]=2024-01-01,2024-12-31
GET /query/posts?filter[views_count][gte]=1000&sort=views_count:desc
Opérateurs typiques : eq, neq, in, like, gte, lte, between, etc.
5. Actions personnalisées
En plus de create, update, delete, vous pouvez définir des actions métier. Ex. PublishPost :
// app/Actions/QueryGate/Posts/PublishPost.php
class PublishPost extends AbstractQueryGateAction
{
public function action(): string { return 'publish'; }
public function handle($request, $model, array $payload)
{
$model->update(['status' => 'published', 'published_at' => now()]);
return ['message' => 'Post publié !', 'post' => $model];
}
public function authorize($request, $model): ?bool
{
return $request->user()->can('update', $model);
}
}
Route générée : POST /query/posts/{id}/publish.
L’exemple du dépôt propose aussi : unpublish, archive, feature, duplicate, approve/reject/spam pour les commentaires.
6. Versioning d’API
Adapter filtres et select selon une version (header X-Query-Version) :
QueryGate::make()
->version('2024-01-01', fn (QueryGate $gate) => $gate
->filters(['title' => 'string', 'status' => 'string'])
->select(['id', 'title', 'status']))
->version('2025-01-01', fn (QueryGate $gate) => $gate
->filters(['title' => 'string', 'status' => 'string', 'views_count' => 'integer', 'author.name' => 'string'])
->select(['id', 'title', 'status', 'views_count', 'author.name']));
Changelog : GET /query/posts/__changelog.
7. Documentation OpenAPI
- GET /query/docs — Interface interactive (Swagger UI ou équivalent)
- GET /query/docs.json — Spécification OpenAPI
La doc est dérivée des filtres, validations et routes déclarées.
Dépannage
| Symptôme | Cause possible | Correctif |
|---|---|---|
| 404 sur /query/posts | Modèle non enregistré dans config/query-gate.php |
Ajouter le modèle dans models et vider le cache de config |
| Filtre ignoré ou erreur | Nom de colonne/relation ou opérateur non autorisé | Vérifier filters et allowedFilters ; les noms doivent correspondre (y compris author.name) |
| Action non trouvée | Classe d’action non enregistrée ou action() mal nommé |
Suivre la convention de nommage et d’enregistrement des actions du package |
Bonnes pratiques
- Restreindre
allowedFiltersetselectpour limiter la surface d’attaque et les fuites de données. - Utiliser middleware (auth, throttle) et authorize dans les actions personnalisées.
- Versioning dès qu’une API est consommée par des clients externes.
Ressources
- Jeffleyd – Build Complete REST APIs with Laravel Query Gate (Medium)
- GitHub – behindsolution/laravel-query-gate
- Exemple – LQG-example
- Documentation – laravelquerygate.com
Cet article s’inscrit dans notre série de guides technique et développement web. Pour un serveur ou une application sur-mesure, contact.