Skip to content

Migration Guides

Darius Matulionis edited this page Jan 7, 2026 · 4 revisions

Migrate from 9.0 to 10.0

Overview

Version 10.0 removes support for Doctrine Annotations (which has been abandoned) and migrates to PHP 8 native Attributes for OpenAPI documentation. This is a breaking change that requires updating your annotation syntax.

Breaking Changes

1. Doctrine Annotations Removed

What changed:

  • The doctrine/annotations package has been removed as a dependency
  • L5-Swagger now uses PHP 8 Attributes exclusively
  • The default analyser now uses AttributeAnnotationFactory instead of DocBlockAnnotationFactory

Action required:

  • Migrate all DocBlock annotations to PHP 8 Attributes

2. Minimum Version Requirements Updated

New requirements:

  • Laravel: ^12.1 or ^11.44 (previously ^12.0 or ^11.0)
  • swagger-php: ^5.7 (previously ^5.0.0)
  • PHP: ^8.2 (unchanged, but attributes require PHP 8.1+)

Action required:

  • Update your composer.json if you have version constraints
  • Run composer update darkaonline/l5-swagger

Migration Steps

Step 1: Update Composer Dependencies

composer update darkaonline/l5-swagger

This will automatically remove the doctrine/annotations dependency and update to swagger-php 5.7.

Step 2: Convert Annotations to Attributes

You need to convert all your OpenAPI annotations from DocBlock syntax to PHP 8 Attribute syntax.

Before (v9.x - DocBlock Annotations):

<?php

namespace App\Http\Controllers;

/**
 * @OA\Info(
 *     version="1.0.0",
 *     title="My API",
 *     description="API description",
 *     @OA\Contact(
 *         email="contact@example.com"
 *     ),
 *     @OA\License(
 *         name="Apache 2.0",
 *         url="https://www.apache.org/licenses/LICENSE-2.0.html"
 *     )
 * )
 */
class Controller
{
}
<?php

namespace App\Http\Controllers;

/**
 * @OA\Get(
 *     path="/api/users",
 *     summary="Get users list",
 *     tags={"Users"},
 *     @OA\Response(
 *         response=200,
 *         description="Successful operation",
 *         @OA\JsonContent(
 *             type="array",
 *             @OA\Items(ref="#/components/schemas/User")
 *         )
 *     )
 * )
 */
public function index()
{
    //
}

After (v10.0 - PHP 8 Attributes):

<?php

namespace App\Http\Controllers;

use OpenApi\Attributes as OA;

#[OA\Info(
    version: "1.0.0",
    title: "My API",
    description: "API description",
    contact: new OA\Contact(
        email: "contact@example.com"
    ),
    license: new OA\License(
        name: "Apache 2.0",
        url: "https://www.apache.org/licenses/LICENSE-2.0.html"
    )
)]
class Controller
{
}
<?php

namespace App\Http\Controllers;

use OpenApi\Attributes as OA;

#[OA\Get(
    path: "/api/users",
    summary: "Get users list",
    tags: ["Users"],
    responses: [
        new OA\Response(
            response: 200,
            description: "Successful operation",
            content: new OA\JsonContent(
                type: "array",
                items: new OA\Items(ref: "#/components/schemas/User")
            )
        )
    ]
)]
public function index()
{
    //
}

Step 3: Update Complex Annotations

For more complex schemas, the conversion follows the same pattern:

Before (v9.x):

/**
 * @OA\Schema(
 *     schema="User",
 *     type="object",
 *     required={"id", "name", "email"},
 *     @OA\Property(
 *         property="id",
 *         type="integer",
 *         description="User ID"
 *     ),
 *     @OA\Property(
 *         property="name",
 *         type="string",
 *         description="User name"
 *     ),
 *     @OA\Property(
 *         property="email",
 *         type="string",
 *         format="email",
 *         description="User email"
 *     )
 * )
 */
class User
{
}

After (v10.0):

use OpenApi\Attributes as OA;

#[OA\Schema(
    schema: "User",
    type: "object",
    required: ["id", "name", "email"],
    properties: [
        new OA\Property(
            property: "id",
            type: "integer",
            description: "User ID"
        ),
        new OA\Property(
            property: "name",
            type: "string",
            description: "User name"
        ),
        new OA\Property(
            property: "email",
            type: "string",
            format: "email",
            description: "User email"
        )
    ]
)]
class User
{
}

Step 4: Update Security Definitions

Before (v9.x):

/**
 * @OA\SecurityScheme(
 *     securityScheme="bearerAuth",
 *     type="http",
 *     scheme="bearer",
 *     bearerFormat="JWT"
 * )
 */

After (v10.0):

use OpenApi\Attributes as OA;

#[OA\SecurityScheme(
    securityScheme: "bearerAuth",
    type: "http",
    scheme: "bearer",
    bearerFormat: "JWT"
)]

Step 5: Regenerate Documentation

After converting all annotations:

php artisan l5-swagger:generate

Or if using multiple documentation sets:

php artisan l5-swagger:generate --all

Step 6: Verify Your Documentation

  1. Visit your Swagger UI endpoint (default: /api/documentation)
  2. Verify all endpoints, schemas, and parameters are correctly displayed
  3. Test the interactive documentation to ensure everything works

Optional: Custom Analyser Configuration

If you were using a custom analyser in your config, you may need to update it to use the new attribute-based system. The default analyser now uses:

new \OpenApi\Analysers\ReflectionAnalyser([
    new \OpenApi\Analysers\AttributeAnnotationFactory(),
])

If you want to support both DocBlock and Attributes temporarily (not recommended for new projects):

// In config/l5-swagger.php
'scanOptions' => [
    'analyser' => new \OpenApi\Analysers\ReflectionAnalyser([
        new \OpenApi\Analysers\AttributeAnnotationFactory(),
        new \OpenApi\Analysers\DocBlockAnnotationFactory(),
    ]),
],

You will also need to add doctrine/annotations to your own composer.json as a requirement.

Note: This dual-mode support is only for gradual migration. The long-term recommendation is to use Attributes exclusively.

Troubleshooting

Error: "Undefined constant OA\Info"

Cause: Missing use OpenApi\Attributes as OA; statement

Solution: Add the import at the top of your file:

use OpenApi\Attributes as OA;

Error: Annotations not being detected

Cause: Not using the correct PHP 8 attribute syntax

Solution: Ensure you're using #[OA\...] not @OA\... and that nested elements use new OA\...

Documentation is empty after upgrade

Cause: Annotations were not properly converted or files aren't being scanned

Solution:

  1. Verify all files are in the scan path (check config/l5-swagger.phppaths.annotations)
  2. Ensure all annotations have been converted to attributes
  3. Clear cache: php artisan cache:clear and php artisan config:clear
  4. Regenerate: php artisan l5-swagger:generate

Resources

Need Help?

If you encounter issues during migration:


Migrate from <7.0 to 8.0

  • Remove config/l5-swagger.php file (make a copy if needed)
  • Remove resources/views/vendor/l5-swagger directory
  • Run php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider" to publish new swagger-ui view and configuration
  • Edit your config/l5-swagger.php file

Migrate from 3.0|4.0 to 5.0

  • Remove config/l5-swagger.php file (make a copy if needed)
  • Remove public/vendor/l5-swagger directory
  • Remove resources/views/vendor/l5-swagger directory
  • Run l5-swagger:publish to publish new swagger-ui view and configuration
  • Edit your config/l5-swagger.php file

Migrate from 2.0 to 3.0

  • Replace $this->app->register('\Darkaonline\L5Swagger\L5SwaggerServiceProvider'); with $this->app->register(\L5Swagger\L5SwaggerServiceProvider::class); in your AppServiceProvider or add \L5Swagger\L5SwaggerServiceProvider::class line in your config/app.php file
  • Run l5-swagger:publish-config to publish new config and make your changes if needed
  • Remove public/vendor/l5-swagger directory
  • Remove resources/views/vendor/l5-swagger directory
  • Run l5-swagger:publish-assets to publish new swagger-ui assets
  • Run l5-swagger:publish-views to publish new views