This package aims to bring the easiest path to creating a Swagger / OpenApi 3 config for your Laravel API's.
For local only installation go here
composer require riconijeboer/laravel-to-swagger
php artisan vendor:publish --provider="RicoNijeboer\Swagger\SwaggerServiceProvider"
- This will publish the package's config-file and migrations
composer require riconijeboer/laravel-to-swagger --dev
php artisan vendor:publish --provider="RicoNijeboer\Swagger\SwaggerServiceProvider"
- This will publish the package's config-file and migrations
- Finally, you should prevent the Swagger package from being auto-discovered by adding the following to your
composer.json
file:"extra": { "laravel": { "dont-discover": [ "riconijeboer/laravel-to-swagger" ] } }
- Now that auto-discovery is disabled you should manually register the service provider in the
register
method of yourApp\Providers\AppServiceProvider
class. In the example we only enable the package when we are running in alocal
environment./** * Register any application services. * * @return void */ public function register() { if ($this->app->environment('local')) { $this->app->register(\RicoNijeboer\Swagger\SwaggerServiceProvider::class); } }
- PHP: 7.4.x or 8.0.x
- Laravel: v6 / v7 / v8
When changes are made that impact existing users, I will make sure that they are documented in the Changelog.
These will contain changes like database columns added / removed / renamed. Or functional changes that need action within your code.
- When updating from v2.1 to v2.2 add a nullable
route_domain
string-column to theswagger_batches
domain.
$table->string('route_domain')->nullable();
Reading a Swagger config is an acquired taste. To display the config in a more user-friendly way I've used Redoc. To register the documentation route you can simply
add the code below to your routes/web.php
file or within a ServiceProvider.
use RicoNijeboer\Swagger\Swagger;
Swagger::routes();
use RicoNijeboer\Swagger\Http\Routing\RouteRegistrar;
use RicoNijeboer\Swagger\Swagger;
Swagger::routes(fn (RouteRegistrar $routes) => $routes->forDocumentation('/different-url/docs'));
use RicoNijeboer\Swagger\Swagger;
Swagger::routes(null, [
'prefix' => 'swagger', // This will do Route::group(['prefix' => 'swagger']) under the hood.
]);
You can disable Redoc and use Swagger UI instead by passing false
as the second parameter to the forDocumentation
method.
use RicoNijeboer\Swagger\Http\Routing\RouteRegistrar;
use RicoNijeboer\Swagger\Swagger;
Swagger::routes(fn (RouteRegistrar $routes) => $routes->forDocumentation('/docs', false));
To add routes to your Swagger config you want to add the \RicoNijeboer\Swagger\Http\Middleware\SwaggerReader
middleware. Which is aliased to both swagger_reader
and openapi_reader
.
Route::middleware('swagger_reader')->get('products', [ProductController::class,'index']);
To group multiple routes in Swagger you add a tag to the path. Using the package you may register a tag through adding a middleware to your route and supplying it with the desired tags as shown below.
Keep in mind that the
swagger_tag
(\RicoNijeboer\Swagger\Http\Middleware\SwaggerTag
) middleware is only going to tag your request once the batch has been stored. If a batch has not been created it will continue and do nothing, no questions asked.
// Using the SwaggerReader middleware
Route::middleware('swagger_reader:tag-one,tag-two')->get('products', [ProductController::class,'index']);
// Using the SwaggerTag middleware
Route::middleware('swagger_tag:tag-one,tag-two')->get('products', [ProductController::class,'index']);
You may want your database entries from the Laravel to Swagger package in a separate database or to have an extra prefix. To do this, add an extra connection to your Laravel project and just simply
set the swagger.database.connection
config value.
For example, if I want all parts of the Swagger database to be in a connection I've named swagger
, I'd set the config like below.
return [
//...
'database' => [
'connection' => 'swagger',
],
//...
];
By default, the package only updates the configuration of your route every 12 hours, within a couple restraints. This does keep into account the response codes you are sending back to your users.
If you want to change this to for example 24 hours, you'd set the swagger.evaluation-delay
config value to the time in seconds.
return [
//...
'evaluation-delay' => 24 * 60 * 60, // Or 86400
//...
];
Swagger allows you to provide the users with a bit of info about your API; a title, a description and a version.
In the config there is a swagger.info
array where you can add your API's title, description and version, as shown below.
return [
//...
'info' => [
'title' => 'Laravel to Swagger',
'description' => null,
'version' => '2.1.2',
],
//...
];
Swagger allows you to show the user servers that you can access the API from. A basic setup would be the one below;
- You have one API where your users can access live data and one where they can access some demo information.
return [
//...
'servers' => [
[
'url' => 'http://api.example.com/v1',
'description' => null,
],
[
'url' => 'http://demo-api.example.com/v1',
'description' => 'The demo environment description',
],
],
//...
];
Swagger also supports Server templating. You are able to add variables to your server which gives you the possibility to obfuscate the urls a bit.
An example from their documentation is a server where you have https://{customerId}.saas-app.com:{port}/v2
as the URL. This is translated to their Yaml as shown below. They define the url,
containing its variables, and describe what the variables do and what their default values are.
Laravel to Swagger supports basically the same format as the Yaml file, below the Yaml you can see how you translate it to the Swagger config. I've added very light validation to this, so if the Swagger UI / Redoc UI breaks try to first ensure that you've correctly configured the config according to the Swagger docs
Swagger Yaml
servers:
- url: https://{customerId}.saas-app.com:{port}/v2
variables:
customerId:
default: demo
description: Customer ID assigned by the service provider
port:
enum:
- '443'
- '8443'
default: '443'
Laravel to Swagger Config
return [
//...
'servers' => [
[
'url' => 'https://{customerId}.saas-app.com:{port}/v2',
'variables' => [
'customerId' => [
'default' => 'demo',
'description' => 'Customer ID assigned by the service provider',
],
'port' => [
'enum' => [
'443',
'8443',
],
'default' => '443',
],
],
],
],
//...
];
Let's say you run into a bug within the Redoc that the team behind Redoc has fixed in a newer version, and I have not updated the package yet to have the fixed version used. I have added a config
value (swagger.redoc.version
), so you don't have to mess around with things like published views or anything; You can simply change the version based on
their releases, at the time of writing this documentation the latest version is v2.0.0-rc.53
.
return [
//...
'redoc' => [
'version' => 'v2.0.0-rc.53',
//...
],
//...
];
If you are using Redoc you are able to group your tags by using the config. In the example below a group called "User Management" is created containing the tags "Users", "Admin" and "API keys".
Tags that are not grouped by you will be added under a default group,
the name of which can be changed using the config (swagger.redoc.default-group
)
return [
//...
'redoc' => [
//...
'default-group' => null,
'tag-groups' => [
[
'name' => 'User Management',
'tags' => [ 'Users', 'Admin', 'API keys' ],
],
],
],
//...
];
You can add a logo to the sidebar in your Redoc visualization by adding a full-url to the swagger.info.logo.url
.
The logo is only displayed when you use the Redoc documentation route.
return [
//...
'info' => [
//...
'logo' => [
'url' => 'https://picsum.photos/300/200',
],
],
//...
];
composer test
The MIT License (MIT). Please see License File for more information.
All notable changes can be found in the CHANGELOG.md.