vyuldashev/laravel-openapi

repository·master·Indexed 19 days ago

https://github.com/vyuldashev/laravel-openapi

A tool for Laravel applications to automatically generate OpenAPI (Swagger) specifications. It enables automated documentation of API endpoints, request schemas, and response structures directly from the Laravel codebase using attributes and factories. Key features include support for multiple document collections, path and component middlewares for data transformation, and Artisan commands for scaffolding request bodies and parameters.

Tokens
7.1K
Snippets
33
Records
34
Agent score
66%

What's inside laravel-openapi

  1. Overview of laravel-openapi

    master
    The vyuldashev/laravel-openapi package allows developers to generate OpenAPI specifications directly from Laravel applications. This enables automated documentation of API endpoints, request schemas, and response structures based on your Laravel codebase.
  2. Make responses reusable in the OpenAPI components section

    master

    To avoid duplicating response definitions in your OpenAPI specification, you can make a response reusable. Implement the Vyuldashev\LaravelOpenApi\Contracts\Reusable interface in your response factory class.

    When a factory implements Reusable, the response is added to the components/responses section of the OpenAPI document, and the controller method will use a $ref to point to it instead of defining the full object inline.

    use Vyuldashev\\LaravelOpenApi\\Contracts\Reusable;
    
    class ErrorValidationResponse extends ResponseFactory implements Reusable
    {
        public function build(): Response
        {
            $response = Schema::object()->properties(
                Schema::string('message')->example('The given data was invalid.'),
                Schema::object('errors')
                    ->additionalProperties(
                        Schema::array()->items(Schema::string())
                    )
                    ->example(['field' => ['Something is wrong with this field!']])
            );
    
            return Response::create('ErrorValidation')
                ->description('Validation errors')
                ->content(
                    MediaType::json()->schema($response)
                );
        }
    }
  3. How Collections work in Laravel OpenAPI

    master

    Collections allow you to declare and manage multiple distinct OpenAPI document configurations within a single Laravel application. By default, the openapi.php configuration file contains a single collection named default.

    You can define additional collections by adding entries to the collections array in your openapi.php config file, where the key is the name of the collection.

    To ensure specific components are included in a particular collection, use the @OpenApi\Collection annotation on your classes (Schemas) or controller methods.

    /**
     * @OpenApi\Collection(name = "v1")
     **/
    class QuoteOfferSchema extends SchemaFactory implements Reusable
    {
        ...
    }
  4. Automatically include route parameters from method arguments

    master

    For standard Laravel route parameters (e.g., /users/{user}), you do not need to manually create a Parameters factory. The package automatically detects route parameters from the controller method arguments.

    To add a description to a route parameter in the generated OpenAPI spec, use the @param PHPDoc tag in the method's docblock.

    Example:

    use Vyuldashev\\LaravelOpenApi\Attributes as OpenApi;
    
    class UserController extends Controller 
    {
        /**
         * Show user.
         * 
         * @param User $user User ID
         */
         #[OpenApi\Operation]
        public function show(User $user)
        {
            //
        }
    }
    use Vyuldashev\LaravelOpenApi\Attributes as OpenApi;
    
    class UserController extends Controller 
    {
        /**
         * Show user.
         * 
         * @param User $user User ID
         */
         #[OpenApi\Operation]
        public function show(User $user)
        {
            //
        }
    }
  5. Add Path Middlewares to transform route data

    master

    Path middlewares allow you to transform OpenAPI data at specific lifecycle points during the generation process.

    To implement a path middleware:

    1. Create a class that implements \Vyuldashev\LaravelOpenApi\Contracts\PathMiddleware.
    2. Register the class in your configuration file under the openapi.collections.default.middlewares.paths array using its fully qualified class name.

    Available lifecycle points:

    • before: Triggered after all RouteInformation has been collected, but before they are processed.
    • after: Triggered after the PathItem has been built.
    // In your config/openapi.php
    'collections' => [
        'default' => [
            'middlewares' => [
                'paths' => [
                    MyPathMiddleware::class,
                ],
            ],
        ],
    ],
  6. Add routes to OpenAPI specification using attributes

    master

    Routes are not automatically included in the generated OpenAPI specification. To include a route, you must apply two attributes:

    1. #[OpenApi\\PathItem] on the controller class.
    2. #[OpenApi\Operation] on the specific action method.

    The summary and description fields in the generated OpenAPI paths object are derived from the DocBlock comments of the controller method.

    use Vyuldashev\LaravelOpenApi\Attributes as OpenApi;
    
    #[OpenApi\PathItem]
    class UserController extends Controller
    {
        /**
         * Create new user.
         *
         * Creates new user or returns already existing user by email.
         */
         #[OpenApi\Operation]
        public function store(Request $request)
        {
            //
        }
    }
  7. Define multiple responses for a single controller method

    master

    You can declare multiple #[OpenApi\Response] attributes on a single controller method to represent different outcomes (e.g., 201 Created, 401 Unauthorized, 422 Unprocessable Entity).

    Important: Even if your response factory's build() method defines a status code, you must explicitly provide the statusCode parameter in the #[OpenApi\Response] attribute in your controller. If you omit the statusCode in the attribute, only one response will be included in the final OpenAPI result.

    use Vyuldashev\\LaravelOpenApi\\Attributes as OpenApi;
    
    class UserController extends Controller
    {
        /**
         * Create user.
        */
        #[OpenApi\Response(factory: CreatedUserResponse::class, statusCode: 201)]
        #[OpenApi\Response(factory: ErrorUnauthenticatedResponse::class, statusCode: 401)]
        #[OpenApi\Response(factory: ErrorForbiddenResponse::class, statusCode: 403)]
        #[OpenApi\Response(factory: ErrorNotFoundResponse::class, statusCode: 404)]
        #[OpenApi\Response(factory: ErrorValidationResponse::class, statusCode: 422)]
        public function store(Request $request)
        {
            //
        }
    }
  8. Add Component Middlewares to transform component data

    master

    Component middlewares allow you to transform OpenAPI components (like schemas or security schemes) after they have been constructed.

    To implement a component middleware:

    1. Create a class that implements \Vyuldashev\LaravelOpenApi\Contracts\ComponentMiddleware.
    2. Register the class in your configuration file under the openapi.collections.default.middlewares.components array using its fully qualified class name.

    Available lifecycle points:

    • after: Triggered after the Components object has been built.
    // In your config/openapi.php
    'collections' => [
        'default' => [
            'middlewares' => [
                'components' => [
                    MyComponentMiddleware::class,
                ],
            ],
        ],
    ],
  9. Apply security to individual operations using Attributes

    master

    To apply a specific security scheme to a single API endpoint, use the #[OpenApi\\]Operation attribute on the controller method. Pass the name of the security scheme to the security parameter.

    use Vyuldashev\
    LaravelOpenApi\\Attributes as OpenApi;
    
    #[OpenApi\\PathItem]
    class UserController extends Controller
    {
        /**
         * Create new user.
         * 
         * Creates new user or returns already existing user by email.
         */
         #[OpenApi\\Operation(security: 'BearerTokenSecurityScheme')]
        public function store(Request $request)
        {
            //
        }
    }
  10. Create an OpenAPI response factory

    master

    To define an OpenAPI response, first generate a new response factory using the Artisan command. Then, extend the ResponseFactory class and implement the build() method, which must return a Response object.

    1. Generate the factory: php artisan openapi:make-response Name

    2. Implement the build() method in the generated class.

    php artisan openapi:make-response ListUsers
    class ListUsersResponse extends ResponseFactory
    {
        public function build(): Response
        {
            return Response::ok()->description('Successful response');
        }
    }
  11. Specify HTTP methods for operations

    master

    When a controller method handles multiple HTTP verbs (common in Laravel resource controllers where update might handle both PUT and PATCH), the generator defaults to including only the first method.

    To specify a specific HTTP verb for an operation, use the method parameter in the #[OpenApi\Operation] attribute.

    use Vyuldashev\LaravelOpenApi\Attributes as OpenApi;
    
    class UserController extends Controller
    {
        /**
         * Update user.
         *
         * Updates a user.
         *
         */
        #[OpenApi\Operation(tags: ['tags'], method: 'PATCH')]
        public function update(Request $request)
        {
            //
        }
    }