endanguyen/yaml-swagger-laravel
Laravel package that integrates Swagger/OpenAPI docs defined in YAML. Load and serve YAML-based API specifications in a Laravel app to generate interactive documentation and keep definitions versionable alongside your code.
Installation
composer require endanguyen/yaml-swagger-laravel
Publish the config file (if needed):
php artisan vendor:publish --provider="Endanguyen\YamlSwaggerLaravel\YamlSwaggerServiceProvider" --tag="config"
Basic Setup
config/yaml-swagger.php (if published):
'output_path' => storage_path('app/swagger'),
'filename' => 'api.yaml',
'generate_on_demand' => false, // Set to true for manual generation
First Use Case
php artisan swagger:generate
storage/app/swagger/api.yaml.Automated Generation
generate_on_demand: false in config to auto-generate YAML on every php artisan command (e.g., optimize, migrate).composer.json:
"scripts": {
"post-autoload-dump": "php artisan swagger:generate"
}
Manual Generation
php artisan swagger:generate --force
Versioning
.env variables) to generate versioned YAML files:
'filename' => env('SWAGGER_VERSION', 'api') . '.yaml',
Route-Based Annotations
routes/api.php with Swagger tags:
Route::get('/users', [UserController::class, 'index'])
->middleware('auth:api')
->swagger([
'tags' => ['Users'],
'summary' => 'Get all users',
'description' => 'Returns paginated user list',
]);
Controller Annotations
/**
* @OA\Get(
* path="/users/{id}",
* tags={"Users"},
* summary="Get a user by ID",
* @OA\Parameter(ref="#/components/parameters/UserId"),
* @OA\Response(response=200, ref="#/components/schemas/User")
* )
*/
public function show(User $user) { ... }
Schema Reusability
app/Http/Resources/SwaggerSchemas.php) and reference them:
/**
* @OA\Schema(
* schema="User",
* type="object",
* required={"id", "name"},
* @OA\Property(property="id", type="integer"),
* @OA\Property(property="name", type="string")
* )
*/
CI/CD Pipeline
- name: Generate Swagger YAML
run: php artisan swagger:generate
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: swagger-yaml
path: storage/app/swagger/api.yaml
Annotation Parsing Issues
@OA\ prefix).Caching Conflicts
generate_on_demand: true, stale YAML files may persist after code changes.--force flag:
php artisan swagger:generate --force
Namespace Conflicts
App\Http\Controllers\Api\V1\UserController) may not resolve correctly.swagger facade is properly bound or use fully qualified paths in annotations:
use OpenApi\Annotations as OA;
Missing Dependencies
zircote/swagger-php for parsing. If not installed, generation fails silently.composer.json:
composer require zircote/swagger-php
Large Projects
'exclude' => [
'App\Http\Controllers\Admin*',
'routes/admin.php',
],
Enable Verbose Output
-v flag to debug parsing:
php artisan swagger:generate -v
Inspect Intermediate Files
storage/logs/laravel.log for parsing errors or missing annotations.Validate YAML
yamllint storage/app/swagger/api.yaml
Test Incrementally
php artisan swagger:generate --controller=UserController
Custom Generators
// app/Providers/YamlSwaggerServiceProvider.php
public function register()
{
$this->app->bind(YamlSwaggerGenerator::class, function ($app) {
return new CustomYamlSwaggerGenerator($app['config']);
});
}
Post-Processing
swagger.generated event to modify the YAML (e.g., add server URLs):
// app/Providers/EventServiceProvider.php
protected $listen = [
'swagger.generated' => [
\App\Listeners\AddServerUrl::class,
],
];
Dynamic Filenames
// config/yaml-swagger.php
'filename' => function () {
return 'api-' . strtolower(app()->environment()) . '.yaml';
},
Integration with API Docs
Route::get('/swagger.yaml', function () {
return response()->file(storage_path('app/swagger/api.yaml'));
});
How can I help you explore Laravel packages today?