# API Versioning in Laravel 11

### Why Version Your Laravel App?

As a backend engineer, versioning your app is an essential workflow in development. It allows you to make necessary updates without disrupting existing environments or breaking earlier versions of your API. Versioning also helps frontend engineers know exactly which version of the API they’re working with, promoting smoother collaboration.

### Versioning in Laravel 11 vs. Earlier Versions

In previous Laravel versions, API versioning was typically configured in the `RouteServiceProvider.php` file located in the `app/Providers` directory. Here's what the setup looked like:

```php
namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
    public const HOME = '/home';

    public function boot(): void
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });

        $this->routes(function () {
            Route::middleware('api')
                ->prefix('api')
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->group(base_path('routes/web.php'));
        });
    }
}
```

**Key Breakdown:**

1. `$this->routes(function () {...});`: Loads and groups routes for both web and API.
    
2. `Route::middleware('api')`: Applies `api` middleware (handles rate limiting and request formatting).
    
3. `->prefix('api')`: Prefixes all API routes with `/api`.
    
4. `->group(base_path('routes/api.php'))`: Loads API routes from `routes/api.php`.
    
5. `Route::middleware('web')`: Loads web-based routes.
    
6. `->group(base_path('routes/web.php'))`: Loads web routes from `routes/web.php`.
    

### Versioning in Laravel 11

Laravel 11 introduces changes aimed at reducing unnecessary files and providing better abstraction. As a result, `RouteServiceProvider.php` is no longer scaffolded by default. Instead, versioning configuration happens in `bootstrap/app.php`.

Here’s how the new setup looks:

```php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
        then: function (){
            Route::middleware('api')
                ->prefix('api/v1')
                ->group(__DIR__.'/../routes/api_v1.php');
        }
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();
```

**Key Breakdown:**

1. `web: __DIR__.'/../routes/web.php'`: Loads web routes.
    
2. `api: __DIR__.'/../routes/api.php'`: Loads API routes.
    
3. `commands: __DIR__.'/../routes/console.php'`: Loads Artisan console commands.
    
4. `health: '/up'`: Sets up a health check endpoint.
    
5. `then: function () {...}`: Adds versioning logic for API routes. It creates a versioned group (`api/v1`).
    

This method allows flexibility and maintains API versioning control.

### Generating API Routes

To start, you need to generate the `api.php` file, which isn’t scaffolded by default in Laravel 11. Run:

```bash
php artisan install:api
```

This will create the `routes/api.php` file. Now, copy this file and rename it to `api_v1.php` to match the version prefix used in `bootstrap/app.php`. This file will handle all your version 1 (`/api/v1/`) endpoints.

Next, define your routes inside `api_v1.php`:

```php
Route::apiResource('tickets', TicketController::class);
```

The `apiResource` method generates routes for API-specific CRUD operations in a streamlined manner, excluding web-specific routes like `create` and `edit`.

### Creating the Controller

Run the following command to create the necessary controller:

```bash
php artisan make:controller "Api/V1/TicketController" --resource --model=Ticket --request
```

This command generates a resource controller (`TicketController`) in the `Api/V1` namespace, with CRUD methods linked to the `Ticket` model. The `--request` flag also generates a form request class for handling validation.

### Testing Your API

You can now test your versioned API in Postman by using endpoints like:

```plaintext
http://ticketeer.test/api/v1/tickets
```

I hope now you get to know how to build and test versioned APIs in Laravel 11.  
  
I’m sharing what I’ve learned about Laravel over the past few weeks as I’ve been getting familiar with it. For those with more experience in Laravel, feel free to share your feedback or how you’ve approached versioning in your own projects!

---
