bamagid / laraswagger
Automatic Swagger/OpenAPI documentation generator for Laravel applications.
Requires
- php: ^8.1
- laravel/framework: >=10.0
- nikic/php-parser: ^4.18 || ^5.0
- swagger-api/swagger-ui: ^3.0 || >=4.1.3
Requires (Dev)
- larastan/larastan: ^2.9
- laravel/pint: ^1.13
- laravel/prompts: ^0.1.24 || ^1.0
- orchestra/testbench: ^8.0 || ^9.0
- pestphp/pest: ^2.34
- pestphp/pest-plugin-laravel: ^2.3
Suggests
- laravel/prompts: Nicer, terminal-width-aware rendering of swagger:generate's warning/error output on Laravel 10+. Falls back to plain console output if not installed.
Provides
None
Conflicts
None
Replaces
None
README
🌍 Documentation Multilingue
ENGLISH
Introduction
bamagid/laraswagger is a Laravel package that automatically generates Swagger/OpenAPI documentation for your API. It reads your routes, controllers, and validation rules, and turns them into a documentation page — no YAML to write, no annotations to maintain by hand.
🎉 Features
- Automatic documentation: your API docs stay in sync with your code, with no extra commands to run
- Reads your existing validation:
FormRequestclasses and inline$request->validate([...])calls are turned into request body schemas - Custom summaries: describe an endpoint with a simple doc comment
- Real-time updates: regenerated automatically after every artisan command by default
âś… Requirements
- PHP 8.1+
- Laravel 10 and above (any future major version included — the constraint isn't capped)
📦 Installation
composer require bamagid/laraswagger
That's it — no service provider to register, no .env changes required. The package works out of the box.
🛠️ How to use it
1. Generating the documentation
By default, the documentation regenerates automatically after every artisan command (and continuously in the background while php artisan serve is running) — see Controlling when it regenerates to change this. You can also trigger it manually at any time:
php artisan swagger:generate
Neither is actually required before your first visit, though: the documentation page generates it on demand the first time it's needed.
2. Viewing the documentation
The documentation is browsable at:
/api/documentation
This route, its page, and the Swagger UI assets it needs are all served directly by the package — nothing is copied into your public/ folder, and you don't need an api.php routes file for it to work. It's available right after composer require, with no setup step. If you want to customize the page itself, publish it and edit your own copy:
php artisan vendor:publish --tag=laraswagger-views
3. Adding a summary to an endpoint
Document what an endpoint does with a @summary line in its doc comment:
/** * @summary Creates a new article */ public function store(Request $request) { // ... }
That text shows up next to the endpoint in the generated documentation.
4. Excluding a route from the documentation
Add @swagger-ignore to a method's doc comment to leave it out entirely — handy for internal or admin-only endpoints you don't want in the public spec:
/** * @swagger-ignore */ public function destroy(int $id) { // Not documented. }
5. How request bodies get their fields
For POST, PUT and PATCH routes, the generator figures out the request body schema in this order:
- A
FormRequesttype-hinted on the action. Yourrules()method is called as-is, so whatever it returns is what gets documented. - An inline validation call written directly in the method —
$request->validate([...]),Validator::make($data, [...]), or a$rules = [...]array passed tovalidate(). This is read without running your controller code, so it works safely even outside of a real HTTP request. - Neither of the above? Falls back to your database. The generator guesses the table from the controller's name (
ArticleController→articles) and documents its columns instead. Columns Laravel manages itself —id,created_at,updated_at,deleted_at,remember_token,email_verified_at— are always left out, since an API client never submits those.
What rules are understood: all the standard ones (required, string, integer, between:, in:, date, mimes:, ...), plus the common Rule:: helpers (Rule::in(), Rule::unique(), Rule::exists(), Rule::enum(), Rule::email(), Rule::file(), and similar) when they come from a FormRequest.
If a rule can't be understood — a custom rule class, a closure, or something built dynamically at runtime — the field is simply documented as a generic string instead. Nothing breaks and nothing is skipped; you just get a slightly less precise type for that one field. Prefer literal rule arrays or a FormRequest if you want everything typed exactly.
6. Controlling when it regenerates
By default, the documentation regenerates automatically after every artisan command runs. To turn that off and regenerate only when you run swagger:generate yourself, add this to your .env:
AUTO_GENERATE_DOCS=false
7. Customizing the title and description
The generated spec's title and description come from your .env by default:
APP_NAME=My API APP_DESCRIPTION=The description of your API
For more control, publish the config file and edit it directly:
php artisan vendor:publish --tag=laraswagger-config
// config/laraswagger.php return [ 'title' => env('APP_NAME', config('app.name')), 'description' => env('APP_DESCRIPTION', ''), 'auto_generate' => env('AUTO_GENERATE_DOCS', true), ];
8. When something can't be documented
Most of the time, swagger:generate finishes without saying anything. It only speaks up when a route or field is left genuinely undocumented — for example, a controller that no longer exists, or a whole validation array built dynamically at runtime that can't be read:
⚠1 avertissement(s) bloquant(s) rencontré(s) pendant la génération de la documentation.
âžś UserController::store
Un appel de validation a été trouvé, mais son tableau de règles est construit dynamiquement (variable) et ne peut pas être lu sans exécuter de code.
→ Utilisez un tableau littéral ou un FormRequest.
Each entry names the exact controller/method, the field involved, and a short fix — the rest of your documentation is still generated normally. If laravel/prompts is installed (composer require laravel/prompts), this renders as a responsive table instead of the plain block above; it's entirely optional.
If something truly unexpected happens, the command prints a short error (type, message, and where it occurred) and exits with a non-zero status, instead of a raw stack trace. Run with -v to see the full trace.
FRANÇAIS
Introduction
bamagid/laraswagger est un package Laravel qui génère automatiquement la documentation Swagger/OpenAPI de votre API. Il lit vos routes, vos contrôleurs et vos règles de validation, et en fait une page de documentation — sans YAML à écrire, sans annotations à maintenir à la main.
🎉 Fonctionnalités
- Documentation automatique : votre doc reste synchronisée avec votre code, sans commande supplémentaire
- Lecture de vos validations existantes : les classes
FormRequestet les appels$request->validate([...])inline sont transformés en schémas de requête - Résumés personnalisables : décrivez un endpoint avec un simple commentaire
- Mises à jour en temps réel : régénérée automatiquement après chaque commande artisan par défaut
✅ Prérequis
- PHP 8.1+
- Laravel 10 et supérieur (toutes les majeures futures incluses — la contrainte n'a pas de plafond)
📦 Installation
composer require bamagid/laraswagger
C'est tout — aucun service provider à enregistrer, aucune modification du .env requise. Le package fonctionne dès l'installation.
🛠️ Comment l'utiliser
1. Générer la documentation
Par défaut, la documentation est régénérée automatiquement après chaque commande artisan (et en continu en arrière-plan pendant que php artisan serve tourne) — voir Contrôler quand elle se régénère pour changer ce comportement. Vous pouvez aussi la générer manuellement à tout moment :
php artisan swagger:generate
Aucune des deux n'est en fait requise avant votre première visite : la page de documentation la génère à la demande la première fois qu'elle en a besoin.
2. Voir la documentation
La documentation est consultable Ă l'adresse :
/api/documentation
Cette route, sa page, et les assets Swagger UI dont elle a besoin sont tous servis directement par le package — rien n'est copié dans votre dossier public/, et vous n'avez pas besoin d'un fichier routes/api.php pour que ça fonctionne. Elle est disponible juste après composer require, sans aucune étape de mise en place. Pour personnaliser la page elle-même, publiez-la et modifiez votre propre copie :
php artisan vendor:publish --tag=laraswagger-views
3. Ajouter un résumé à un endpoint
Décrivez ce que fait un endpoint avec une ligne @summary dans son commentaire :
/** * @summary Crée un nouvel article */ public function store(Request $request) { // ... }
Ce texte apparaît à côté de l'endpoint dans la documentation générée.
4. Exclure une route de la documentation
Ajoutez @swagger-ignore au commentaire d'une méthode pour l'exclure entièrement — pratique pour les endpoints internes ou réservés aux admins que vous ne voulez pas dans la spec publique :
/** * @swagger-ignore */ public function destroy(int $id) { // Non documenté. }
5. D'oĂą viennent les champs du corps de requĂŞte
Pour les routes POST, PUT et PATCH, le générateur détermine le schéma du corps de requête dans cet ordre :
- Un
FormRequesttypé sur l'action. Votre méthoderules()est appelée telle quelle, donc tout ce qu'elle retourne est documenté. - Un appel de validation inline écrit directement dans la méthode —
$request->validate([...]),Validator::make($data, [...]), ou un tableau$rules = [...]passĂ© Ăvalidate(). C'est lu sans exĂ©cuter votre code de contrĂ´leur, donc ça fonctionne mĂŞme en dehors d'une vraie requĂŞte HTTP. - Ni l'un ni l'autre ? Repli sur votre base de donnĂ©es. Le gĂ©nĂ©rateur devine la table Ă partir du nom du contrĂ´leur (
ArticleController→articles) et documente ses colonnes à la place. Les colonnes gérées par Laravel lui-même —id,created_at,updated_at,deleted_at,remember_token,email_verified_at— sont toujours exclues, puisqu'un client API ne les soumet jamais.
Règles comprises : toutes les règles standard (required, string, integer, between:, in:, date, mimes:, ...), plus les principaux helpers Rule:: (Rule::in(), Rule::unique(), Rule::exists(), Rule::enum(), Rule::email(), Rule::file(), et similaires) quand ils viennent d'un FormRequest.
Si une règle n'est pas comprise — une classe de règle personnalisée, une closure, ou quelque chose construit dynamiquement à l'exécution — le champ est simplement documenté comme une chaîne générique à la place. Rien ne casse et rien n'est ignoré ; vous obtenez juste un type un peu moins précis pour ce champ-là . Préférez des tableaux de règles littéraux ou un FormRequest si vous voulez que tout soit typé exactement.
6. Contrôler quand elle se régénère
Par défaut, la documentation se régénère automatiquement après chaque commande artisan. Pour désactiver ça et ne la régénérer que lorsque vous lancez swagger:generate vous-même, ajoutez ceci à votre .env :
AUTO_GENERATE_DOCS=false
7. Personnaliser le titre et la description
Le titre et la description de la spec générée viennent de votre .env par défaut :
APP_NAME=Mon API APP_DESCRIPTION=La description de votre API
Pour plus de contrĂ´le, publiez le fichier de configuration et modifiez-le directement :
php artisan vendor:publish --tag=laraswagger-config
// config/laraswagger.php return [ 'title' => env('APP_NAME', config('app.name')), 'description' => env('APP_DESCRIPTION', ''), 'auto_generate' => env('AUTO_GENERATE_DOCS', true), ];
8. Quand quelque chose ne peut pas être documenté
La plupart du temps, swagger:generate termine sans rien afficher de particulier. Il ne se manifeste que lorsqu'une route ou un champ reste réellement non documenté — par exemple un contrôleur qui n'existe plus, ou un tableau de validation entier construit dynamiquement à l'exécution et impossible à lire :
⚠1 avertissement(s) bloquant(s) rencontré(s) pendant la génération de la documentation.
âžś UserController::store
Un appel de validation a été trouvé, mais son tableau de règles est construit dynamiquement (variable) et ne peut pas être lu sans exécuter de code.
→ Utilisez un tableau littéral ou un FormRequest.
Chaque entrée indique le contrôleur/la méthode exacts, le champ concerné, et une correction courte — le reste de votre documentation est généré normalement. Si laravel/prompts est installé (composer require laravel/prompts), ce rendu devient un tableau adaptatif au lieu du bloc ci-dessus ; c'est entièrement optionnel.
Si quelque chose de vraiment imprévu se produit, la commande affiche une erreur courte (type, message, et où ça s'est produit) et se termine avec un code de sortie non nul, plutôt qu'une pile d'appels brute. Lancez avec -v pour voir la pile complète.