Creating Documentation and Testing with Swagger OpenAPI for a Laravel API

Creating Documentation and Testing with Swagger OpenAPI for a Laravel API

Understand the process of generating documentation and testing a Laravel API with Swagger OpenAPI

·

6 min read

Introduction

API documentation is an important part of the development process, as it helps to communicate the functionality of an API to developers who will be using it. Swagger OpenAPI is a popular tool for generating API documentation, and it can be easily integrated into a Laravel API.

Setting up Swagger OpenAPI

To set up Swagger OpenAPI for a Laravel API, we'll need to install the swaggervel package. This can be done by running the following command in the root directory of your Laravel project:

composer require "darkaonline/l5-swagger:5.7.*"

Once the package is installed, we need to add the service provider to the providers array in the config/app.php file:

'providers' => [
    // Other service providers...
    Darkaonline\L5Swagger\L5SwaggerServiceProvider::class,
],

Next, we need to publish the configuration file and assets by running the following command:

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

This will create a config/l5-swagger.php configuration file, as well as a public/vendor/swagger-ui directory containing the Swagger UI assets.

To define the structure and behavior of your API, you'll need to create a Swagger OpenAPI specification file in the public/docs directory. This file should be written in YAML or JSON and should define the API's endpoints, request and response bodies, and other details. Here's an example of a basic Swagger OpenAPI specification file for a Laravel API:

openapi: 3.0.1
info:
  title: My Laravel API
  version: 1.0.0
servers:
  - url: https://api.example.com/
paths:
  /users:
    get:
      summary: Get a list of users
      operationId: getUsers
      tags:
        - users
      parameters:
        - name: limit
          in: query
          description: The maximum number of users to return
          required: false
          schema:
            type: integer
      responses:
        '200':
          description: A list of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
components:
  schemas:
    User:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          description: The unique identifier for the user
        name:
          type: string
          description: The name of the user

In this example, the openapi and info blocks define the version of the Swagger OpenAPI specification and the API's metadata, respectively. The servers block defines the base URL for the API, and the paths block defines the API's endpoints and their behavior. The components block defines reusable schemas that can be referenced by the endpoints.

You can then access the documentation by visiting the /docs route in your Laravel application. The Swagger UI will display the documentation and allow users to interact with the API by making requests and viewing the responses.

Defining API Endpoints

With Swagger OpenAPI set up, we can now start defining our API endpoints. We can do this by adding annotations to our controller methods. Here's an example of a simple API endpoint for creating a new user:

/**
 * @OA\Post(
 *     path="/users",
 *     summary="Create a new user",
 *     @OA\RequestBody(
 *         required=true,
 *         @OA\JsonContent(
 *             @OA\Property(property="name", type="string"),
 *             @OA\Property(property="email", type="string"),
 *             @OA\Property(property="password", type="string")
 *         )
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="Successful operation"
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Invalid input"
 *     ),
 *     @OA\Response(
 *         response=401,
 *         description="Unauthorized"
 *     ),
 *     @OA\Response(
 *         response=403,
 *         description="Forbidden"
 *     ),
 *     @OA\Response(
 *         response=404,
 *         description="Resource not found"
 *     )
 * )
 */
public function store(Request $request)
{
    // Validate and create the user...
}

In this example, we're using the @OA\Post annotation to define a POST request to the /users path, with a summary description and request body specification. We also define a set of possible responses, including a successful response (200), as well as responses for invalid input (400), unauthorized access (401), forbidden access (403), and a resource not found (404).

We can also specify additional details for each endpoint, such as query parameters and response examples. Here's an example of an endpoint that retrieves a list of users, with pagination and filtering options:

/**
 * @OA\Get(
 *     path="/users",
 *     summary="Get a list of users",
 *     @OA\Parameter(
 *         name="page",
 *         in="query",
 *         description="The page number",
 *         required=false,
 *         @OA\Schema(type="integer")
 *     ),
 *     @OA\Parameter(
 *         name="per_page",
 *         in="query",
 *         description="The number of items per page",
 *         required=false,
 *         @OA\Schema(type="integer")
 *     ),
 *     @OA\Parameter(
 *         name="name",
 *         in="query",
 *         description="Filter by name",
 *         required=false,
 *         @OA\Schema(type="string")
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="Successful operation",
 *         @OA\JsonContent(
 *             type="array",
 *             @OA\Items(ref="#/components/schemas/User")
 *         )
 *     ),
 *     @OA\Response(
 *         response=401,
 *         description="Unauthorized"
 *     ),
 *     @OA\Response(
 *         response=403,
 *         description="Forbidden"
 *     ),
 *     @OA\Response(
 *         response=404,
 *         description="Resource not found"
 *     )
 * )
 */
public function index(Request $request)
{
    // Retrieve and return a list of users...
}

In this example, we use the @OA\Get annotation to define a GET request to the /users path, and define a set of query parameters using the @OA\Parameter annotation. We also specify a successful response (200) with a JSON array of users, using the @OA\JsonContent and @OA\Items annotations to define the array items and their schema.

Generating the Documentation

With our API endpoints defined, we can now generate the documentation by running the following command:

php artisan l5-swagger:generate

This will generate a public/docs/api-docs.json file containing the Swagger OpenAPI specification for our API. We can then view the documentation by visiting the /docs route in our Laravel application. This will display the Swagger UI, which allows us to interactively explore the API and try out different requests.

Testing the API

In addition to generating documentation, Swagger OpenAPI can also be used for testing our API. We can do this by using the Swagger Codegen tool to generate a client library for our API, which can then be used to make requests and assert on the responses.

To generate a client library using Swagger Codegen, we can run the following command:

java -jar swagger-codegen-cli.jar generate -i public/docs/api-docs.json -l <LANGUAGE> -o <OUTPUT_DIRECTORY>

Replace <LANGUAGE> with the desired language for the client library (e.g. php, python, javascript, etc.), and <OUTPUT_DIRECTORY> with the desired output directory. This will generate the client library in the specified output directory.

Once the client library is generated, we can use it to make requests to our API and assert on the responses. Here's an example of how to do this in PHP:

$client = new Swagger\Client\Api\UsersApi();

$response = $client->createUser([
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'password' => 'password123',
]);

$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('John Doe', $response->getData()->name);

In this example, we create a new instance of the UsersApi class from the generated client library, and use it to make a POST request to the /users endpoint. We then assert that the response has a status code of 200 and that the name field in the response data is correct.

We can also use the client library to test other API endpoints, such as retrieving a list of users:

$client = new Swagger\Client\Api\UsersApi();

$response = $client->getUsers();

$this->assertEquals(200, $response->getStatusCode());
$this->assertCount(10, $response->getData());

In this example, we create a new instance of the UsersApi class and use it to make a GET request to the /users endpoint. We then assert that the response has a status code of 200 and that the data field in the response is an array with 10 items.

Conclusion

In this post, we covered how to set up and use Swagger OpenAPI for generating documentation and testing a Laravel API.

We saw how to define API endpoints using annotations, generate the documentation, and use the Swagger Codegen tool to generate a client library for testing the API.

By following these steps, you can easily add documentation and testing to your Laravel API using Swagger OpenAPI.

Did you find this article valuable?

Support blog.jjdiaz.dev by becoming a sponsor. Any amount is appreciated!