Home » Laravel » How to Use Swagger in Laravel

How to Use Swagger in Laravel

If you need to interact with another developers team or your company wants to have documentation for your API, you can use OpenAPI Framework. Also, it is called Swagger. It is a standard system for API documentation in many companies.

It is very important to have standardized up-to-date documentation because other developers will be able to learn how your API works easily, and you may forget how it works after a few months, so it may helpful for you too. In this article, I will explain how to use Swagger in Laravel.

How to Install Swagger in Laravel

There is the l5-swagger package, which provides support for generating OpenAPI documentation for Laravel. This package can generate JSON or YAML fles with documentation based on PHP annotations. Use this command to install it in the latest Laravel versions:

composer require darkaonline/l5-swagger

After this publish Swagger config and view files using the following command:

php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"

A main configuration file for the package is config/l5-swagger.php. For many projects the default settings are sufficient. By default, you can open the documentation frontend using this path: api/documentation. The documentation has JSON format and the package searches for annotations in the app folder. If you want to add other folders, open the config file and find documentations -> default -> paths -> annotations. Add your extra paths here, for example:

Also, if you want to be able to perform test queries to your API using the Swagger frontend, you must set the L5_SWAGGER_CONST_HOST environment variable in your .env file. For the development server, which is served using artisan it will look like this:

L5_SWAGGER_CONST_HOST="http://localhost:8000"

You can generate the documentation using this command:

php artisan l5-swagger:generate

This command will generate only default documentation. If you have multiple documentations, use the following command to generate them all:

php artisan l5-swagger:generate --all

But don’t do it now. You should add the information about the project and at least one API endpoint to be able to generate documentation.

Most Used Swagger Annotations

Here I will list the most used annotations and their descriptions which you can use in your projects:

  • Info – add information about a whole project;
  • Tag – create a tag for separating endpoints by sections;
  • Get – describe GET request;
  • Post – describe POST request;
  • Delete – describe DELETE request;
  • Post – describe POST request;
  • Put – describe PUT request;
  • Response – describe a response;
  • Schema – describe JSON properties or property parameters, which can be reused in other schemas;
  • Property – describe a field;
  • Items – describe elements of the array;

How to Use Swagger in Laravel

1. Add Project Info

Before generating your first documentation, you should add project info in the @Info annotation. I usually use the app/Http/Controllers/Controller.php class to do this. For example:

/** * @OA\Info( * description="This is an example API", * version="1.0.0", * title="Example API" * ) */ class Controller extends BaseController { //..... }

2. Describe Endpoint

Let’s look at how annotations for any endpoint description should look. All requests must be described using one of these annotations which satisfy to request method @Get, @Post, @Put, @Delete. In the annotation itself, you can set the values ​​of such parameters:

  • path – the URL path to the endpoint;
  • tags – specify tags here if you want to tag this endpoint;
  • summary – short description;
  • description – detailed description;

Also, the root endpoint annotation can contain these annotations:

  • @Parameter – describes a parameter that should be passed in the query or headers;
  • @RequestBody – describes a request body for PUT, POST, and DELETE queries;
  • @Response – describes any possible responses and their status codes;
  • @Security – describes authentication information.

Of course, this is not a full list of supported annotations, but only the most used of them. Here is an example of documentation for the /api/user endpoint. Laravel scaffolding has this endpoint by default, so you can describe it:

/** * @OA\Get( * path="/api/user", * summary="Get current user", * description="Returns information about the current user if the request is authenticated", * @OA\Response( * response=200, * description="Everything OK" * ), * @OA\Response( * response=403, * description="Access Denied" * ) * ) */

There the security parameters are missing, but we will add them later. By default, all documentation should be only in the ./app folder. So you can place the code above in the app/Http/Controllers/Controller.php class for this example. Now you can generate your documentation:

php artisan l5-swagger:generate

You can find the documentation in the HTML format on http://localhost:8000/api/documenation URL for the development server served by artisan:

3. Describe Query Parameters

Here are multiple entities that can be described using the @Parameter annotation:

  • Path – parameter, which can be parsed from query path, for example: /user/{id};
  • Query – parameters, which are added to the query path, for example, /user?id=1;
  • Header – any custom headers;
  • Cookie – any custom cookie.

You must specify these arguments for this annotation:

  • name – the name of the parameter;
  • in – type of the parameter (path, query, header, or cookie);
  • description – a short description of a parameter;
  • required – determines whether the parameter is required. All path parameters are required;
  • deprecated – marks the parameters as deprecated.

Let’s have a look at the example. We can add the verbosity query parameter to the previous request. Add this code before the description of responses. For example:

/** * @OA\Parameter( * name="verbosity", * description="Set the verbosity of the output", * in="query", * required=false * ), */

Also, you can describe the Authentication token which should be passed as a header:

/** * @OA\Parameter( * name="Authentication", * description="Provides user authentication token", * in="header", * required=true * ), */

Now, you can generate documentation and look at the result:

4. Describe JSON

You can use JSON data in responses and even in requests. There is no difference between form-data and JSON request body for Laravel as long as you do not sent files. You can describe JSON content using the @JsonContent annotation. This annotation can contain one or multiple @Property annotations describing each JSON field. The @Property annotation can contain these parameters:

  • property – the name of the field;
  • type – the type of the field. Supported types: integer, number, string, boolean, object, array;
  • description – a short description of the field;
  • format – additional information about the data. It depends on the type of field;
  • example – the example data for displaying;
  • nullable – determines whether the parameter can contain a null value.

The most used string number formats are float and double. String formats are date, date-time, password, binary, byte, email, uuid, uri, hostname, ipv4, ipv6, and others. These are only the most used parameters. Also, it can contain other properties, enumerations, and other stuff. For example, let’s describe the verbosity parameter as JSON:

/** * @OA\JsonContent( * @OA\Property( * property="verbosity", * description="Set the verbosity of the output", * type="boolean", * nullable="true" * ) * ) */

5. Describe Responses

I described only status codes for responses above, but the documentation should contain detailed info about the response data. Most responses in REST APIs are JSON. For example, our API returns this error message:

{ "message": "Unauthenticated" }

The Swagger annotations will look like this:

/** * @OA\Response( * response=403, * description="Access Denied", * @OA\JsonContent( * @OA\Property( * property="message", * type="string", * description="An error message", * nullable=false, * example="Unauthenticated" * ) * ) * ) */

6. Using Schema

In the example above we describe the JSON fields directly in the response annotation. In that case, this is reasonable, because there is only one response with these fields. But in many cases, you may have a set of fields used in multiple endpoints. You can use the @Schema annotation to avoid duplication of the code. It allows to describe all required fields or parameters in one place and then use them everywhere.

Each schema must have the schema parameter with the name. This name will be used for importing the schema. For example, you can describe a schema for the successful response for the /api/user request:

/** * @OA\Schema( * schema="UserSchema", * @OA\Property( * property="id", * type="integer", * description="User ID", * nullable=false, * example="1" * ), * @OA\Property( * property="name", * type="string", * description="User Name", * nullable=false, * example="John" * ), * @OA\Property( * property="email", * type="string", * description="User EMail", * nullable=false, * format="email" * ), * @OA\Property( * property="email_verfied_at", * type="string", * description="User EMail verified date", * nullable=true, * format="date-time" * ), * @OA\Property( * property="created_at", * type="string", * description="Date of user creation", * nullable=false, * format="date-time" * ), * @OA\Property( * property="updated_at", * type="string", * description="Date of last updating user data", * nullable=false, * format="date-time" * ), * ) */

Now, you can add this schema into the response using the ref parameter. Use path “#/components/schemas” plus the schema name:

/** * @OA\Response( * response=200, * description="Everything OK", * @OA\JsonContent( * ref="#/components/schemas/UserSchema" * ) * ), */

It will look like this on the frontend:

You can switch to the schema tab, to show more detailed info:

In this example, I have described the schema for @JsonContent. You also can use a schema for properties itself, arrays, etc.

7. Describe Arrays

Very often APIs return an array of data. You can use the @Property annotation with the type array to describe them. But in this case, the annotation must contain the @Items entry which describes elements of an array. Let’s imagine, that our endpoint returns a list of users in some cases. You can use the following code to describe it:

/** * @OA\Response( * response=201, * description="Users List", * @OA\JsonContent( * @OA\Property( * property="users", * type="array", * description="List of users", * @OA\Items( * ref="#/components/schemas/UserSchema" * ) * ) * ) * ), */

You can place the properties directly into the @Items annotation or just a reference to the existing schema as it is done in the example.

8. Describe Enumerations

Enumerations allow you to describe all possible values for any property. Just describe the property as usual and then use the enum parameter to determine possible values. For example, let’s describe the state field, which can have four values: pending, processing, finished, and failed:

/** * @OA\Property( * property="state", * type="string", * description="Processing state", * nullable=false, * enum={ * "pending", * "processing", * "finished", * "failed", * } * ), */

This field will look like this on the frontend side:

Also, you can describe the field using the @Schema annotation and reuse it wherever you want. Just describe a property schema:

/** * @OA\Schema( * schema="StateEnum", * description="Processing State", * type="string", * enum={ * "pending", * "processing", * "finished", * "failed", * } * ) */

Now, you can import this schema into any property without writing the same code multiple times:

/** * @OA\Property( * property="state", * type="string", * ref="#/components/schemas/StateEnum" * ) */

9. Describe Objects

If you want to describe any object which contains other properties, for example, an element of an array you can use object type and just add child properties into the object property. Let’s describe the object with information about a user with admin privileges:

/** * @OA\Schema( * schema="AdminSchema", * @OA\Property( * property="id", * type="integer", * description="User ID", * nullable=false, * example="1" * ), * @OA\Property( * property="name", * type="string", * description="User Name", * nullable=false, * example="John" * ), * @OA\Property( * property="permissions", * type="object", * nullable=false, * description="Permissions state", * @OA\Property( * property="can_create", * type="boolean", * nullable=false, * description="Determines whether the user can create records", * ), * @OA\Property( * property="can_delete", * type="boolean", * nullable=false, * description="Determines whether the user can delete records", * ), * ) * ) */

10. Combine Schemas

Schemas can do a lot of interesting things. You can combine two or more schemas for describing arrays that can contain multiple types of objects. Here are the most used parameters for schema combination:

  • anyOf – can contain any of the specified schemas or both;
  • allOf – must contain all specified schemas;
  • oneOf – must contain only one of the specified schemas.

These parameters want an array of links on a schema. For example, imagine that your API can return information about admins and regular users in the same list. You can describe this array using the anyOf parameter:

/** * @OA\JsonContent( * @OA\Property( * property="users", * type="array", * description="List of users", * @OA\Items( * anyOf={ * @OA\Schema(ref="#/components/schemas/UserSchema"), * @OA\Schema(ref="#/components/schemas/AdminSchema"), * } * ) * ) * ) */

11. Describe Post Request

Now you know all tips that can help you to create documentation for your projects. You have laernt above how to create documentation for GET requests. Let’s have a look at how to create documentation for POST requests. The main difference here, you can use the @RequestBody annotation with JSON content to describe which fields you want to receive. For example, let’s create documentation for an endpoint which adds a new user:

/** * @OA\Schema( * schema="CreateUserRequest", * @OA\Property( * property="name", * type="string", * description="User Name", * nullable=false, * example="John" * ), * @OA\Property( * property="email", * type="string", * description="User EMail", * nullable=false, * format="email" * ), * ) * * @OA\Post( * path="/api/user", * summary="Create a new user", * description="Creates a new user by its name and email address", * @OA\RequestBody( * @OA\JsonContent(ref="#/components/schemas/CreateUserRequest") * ), * @OA\Response( * response=201, * description="Everything OK", * @OA\Schema(ref="#/components/schemas/UserSchema") * ), * @OA\Response( * response=500, * description="Internal server error" * ) * ) */

I made a dedicated schema for this request because in a real project, you should place it into FormRequest class and then link it to a controller.

12. Tagging Endpoints

You can categorize your endpoints using tags. For example, you can put all endpoints for user management together using the “Users” tag. Create the tag first:

/** * @OA\Tag( * name="Users", * description="API Endpoints of User Management" * ) */

Then, add the tag to the endpoint description using the tags parameter:

/** * @OA\Post( * path="/api/user", * summary="Create a new user", * tags="Users", */

Now it looks prettier:

Swagger Annotations and Sub Classes

It is pretty weird, but when you extend a class which has @Schema annotations, your sub-class inherits the schema. For example, you have CreateArticleRequest with this schema:

/** * @OA\Schema( * schema="ArticleRequestSchema", * @OA\Property( * property="title", * type="string", * description="Article title", * nullable=false, * ), * @OA\Property( * property="content", * type="string", * description="Article content", * nullable=false, * ) * ) */

If you create CreateNewsRequest that extends CreateArticleRequest, and add an empty schema with the name NewsArticleRequestSchema into it, this schema will contain all properties from the parent class.

So, be careful when you are using inheritance with Swagger.

Wrapping Up

In this article, I have explained how to use Swagger in Laravel with the l5-swagger package. As you can see, it may be very convenient. Your documentation can be located as closest as possible to your code so that you can update it regularly.

Your Reaction

Leave a Comment