philiprehberger / laravel-api-versioning
Laravel middleware for API versioning with multi-source resolution from headers, Accept vendor types, and URL path segments
Package info
github.com/philiprehberger/laravel-api-versioning
pkg:composer/philiprehberger/laravel-api-versioning
Fund package maintenance!
Requires
- php: ^8.2
- illuminate/config: ^11.0|^12.0
- illuminate/http: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
Requires (Dev)
- larastan/larastan: ^2.0|^3.0
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0|^10.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^1.12|^2.0
- phpunit/phpunit: ^11.0
README
Laravel middleware for API versioning with multi-source resolution from headers, Accept vendor types, and URL path segments.
Requirements
- PHP 8.2+
- Laravel 11 or 12
Installation
composer require philiprehberger/laravel-api-versioning
Laravel's package auto-discovery registers the service provider automatically.
Publish the config file:
php artisan vendor:publish --tag=api-versioning-config
This creates config/api-versioning.php.
Usage
Configuration
// config/api-versioning.php return [ 'supported_versions' => ['v1', 'v2'], 'default_version' => 'v1', 'latest_version' => 'v2', 'deprecated_versions' => [], 'vendor_name' => 'myapp', 'header' => 'X-API-Version', 'response_headers' => true, ];
Registering the Middleware
// bootstrap/app.php ->withMiddleware(function (Middleware $middleware) { $middleware->alias([ 'api.version' => \PhilipRehberger\ApiVersioning\ApiVersion::class, ]); })
Route::middleware('api.version')->group(function () { // ... });
Accessing the Current Version
use PhilipRehberger\ApiVersioning\ApiVersion; $version = ApiVersion::current($request); // e.g. 'v2'
Version Resolution Priority
X-API-Versionrequest headerAcceptheader vendor type:application/vnd.{vendor_name}.{version}+json- URL path segment:
/api/{version}/... - Configured default version
API
| Method / Concept | Description |
|---|---|
ApiVersion::current(Request $request) |
Get the resolved API version for the current request |
ApiVersion::aliases() |
Get the configured version aliases as an associative array |
ApiVersion::resolveAlias(string $alias) |
Resolve an alias to its version string, or null if not found |
ApiVersion::isDeprecated(string $version) |
Check whether a version is deprecated (in deprecated_versions or not the latest_version) |
ApiVersion middleware |
Resolves version (with alias support), sets request attribute, adds response headers |
X-API-Version response header |
The resolved version for each request |
X-API-Deprecated response header |
true / false — whether this version is deprecated |
Version Aliases
Map friendly names to version strings so clients can request latest or stable instead of a specific version number:
// config/api-versioning.php 'aliases' => [ 'latest' => 'v2', 'stable' => 'v1', ],
When the middleware resolves a version that matches an alias key, it transparently replaces it with the target version. For example, sending X-API-Version: latest is treated as X-API-Version: v2.
You can also resolve aliases programmatically:
use PhilipRehberger\ApiVersioning\ApiVersion; ApiVersion::aliases(); // ['latest' => 'v2', 'stable' => 'v1'] ApiVersion::resolveAlias('latest'); // 'v2' ApiVersion::resolveAlias('unknown'); // null
Deprecation Checks
Check whether a version is deprecated programmatically:
use PhilipRehberger\ApiVersioning\ApiVersion; ApiVersion::isDeprecated('v1'); // true if v1 is in deprecated_versions or not latest_version ApiVersion::isDeprecated('v2'); // false if v2 === latest_version
SemVer-Style Versions
In addition to the simple v1, v2 form, the URL path and Accept header resolvers also match SemVer-style versions like v1.2, v1.2.3, etc. List them in supported_versions to enable:
'supported_versions' => ['v1', 'v1.2', 'v1.2.3', 'v2'],
GET /api/v1.2.3/users
Accept: application/vnd.api.v1.2.3+json
Custom Accept Header Pattern
Override the default application/vnd.{vendor_name}.{version}+json matcher with a custom regex via accept_header_pattern. The first capture group must contain the version string:
// config/api-versioning.php 'accept_header_pattern' => '/application\/json;\s*version=(v\d+(?:\.\d+){0,2})/',
Accept: application/json; version=v2
When accept_header_pattern is null, the default vendor type pattern is used.
Response Headers
| Header | Values | Meaning |
|---|---|---|
X-API-Version |
v1, v2, ... |
The resolved version for this request |
X-API-Deprecated |
true / false |
Whether this version is deprecated |
Unsupported Version Response (400)
{
"error": {
"code": "unsupported_api_version",
"message": "API version 'v99' is not supported.",
"supported_versions": ["v1", "v2"]
}
}
Development
composer install vendor/bin/phpunit vendor/bin/pint --test vendor/bin/phpstan analyse
Support
If you find this project useful: