📚API Versioning Guide
SiroPHP supports API versioning through the `VersionMiddleware`. You can maintain multiple API versions simultaneously, allowing clients to migrate at their own
Overview#
SiroPHP supports API versioning through the VersionMiddleware. You can maintain multiple API versions simultaneously, allowing clients to migrate at their own pace.
Route Prefix Versioning#
Register versioned route prefixes:
use Siro\Core\Middleware\VersionMiddleware;
// Register version-to-prefix mappings
VersionMiddleware::register(1, '/api/v1');
VersionMiddleware::register(2, '/api/v2');
// In routes/api.php, the 'version' middleware is already applied
// to the /api group. Routes will be accessible under:
// /api/v1/products (version 1)
// /api/v2/products (version 2)
Routes registered after VersionMiddleware::register() are automatically duplicated under the versioned prefix.
Defining Version-Specific Routes#
// Both endpoints accessible at /api/v1/products and /api/v2/products
$router->resource('products', ProductController::class, ['auth']);
// Create separate controllers for each version:
// v1: /api/v1/orders
// v2: /api/v2/orders (with new fields)
// Or use the same controller with conditional logic
Header-Based Versioning#
Clients can specify the version via the Accept header:
Accept: application/vnd.siro.v1+json
Accept: application/vnd.siro.v2+json
The middleware reads the header and routes to the appropriate version.
Accessing in Controllers#
Access request metadata to implement version-aware logic:
public function index(Request $request): Response
{
// Check version from URL or header
$path = $request->path();
if (str_contains($path, '/v2/')) {
// Return v2 response format
}
// Default v1 response
}
Middleware Registration#
The version middleware is registered alongside other middleware in TestCase::createApp() or the application bootstrap:
Router::setMiddlewareAliases([
'auth' => \App\Middleware\AuthMiddleware::class,
'throttle' => \Siro\Core\Middleware\ThrottleMiddleware::class,
'cors' => \Siro\Core\Middleware\CorsMiddleware::class,
'json' => \Siro\Core\Middleware\JsonMiddleware::class,
'version' => \Siro\Core\Middleware\VersionMiddleware::class,
'etag' => \Siro\Core\Middleware\EtagMiddleware::class,
'metrics' => \Siro\Core\Middleware\MetricsMiddleware::class,
]);
Best Practices#
- Define all version mappings at the start of
routes/api.phpbefore any routes. - Maintain backward compatibility within a major version — only add fields, don't remove them.
- Deprecate old versions gradually: announce deprecation in response headers, then remove when usage drops to zero.
- Use a sunset policy (e.g. support each version for at least 6 months after replacement is stable).
- Version your database schema logically — don't create separate databases per API version.