### Configure Migration Guides Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Lifecycle Sets up specific migration guide URLs for different API versions within the configuration file. ```php // config/apiroute.php 'documentation' => [ 'migration_guides' => [ 'v1' => 'https://docs.example.com/api/migration/v1-to-v2', 'v2' => 'https://docs.example.com/api/migration/v2-to-v3', ], ], ``` -------------------------------- ### Complete Configuration Example with Version Options Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Comprehensive example of API version configuration, including deprecation, sunset dates, successor, documentation URL, and rate limiting. ```php 'versions' => [ 'v1' => [ 'routes' => base_path('routes/api/v1.php'), 'middleware' => ['auth:sanctum'], 'status' => 'deprecated', 'deprecated_at' => '2025-06-01', 'sunset_at' => '2025-12-01', 'successor' => 'v2', 'documentation' => 'https://docs.myapp.com/api/v1', 'rate_limit' => 100, ], 'v2' => [ 'routes' => base_path('routes/api/v2.php'), 'middleware' => ['auth:sanctum'], 'status' => 'active', 'documentation' => 'https://docs.myapp.com/api/v2', 'rate_limit' => 1000, ], 'v3' => [ 'routes' => base_path('routes/api/v3.php'), 'middleware' => ['auth:sanctum'], 'status' => 'beta', ], ], ``` -------------------------------- ### Header Strategy Example Requests Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Example HTTP requests using the 'X-API-Version' header to specify the API version. ```http GET /api/users HTTP/1.1 Host: example.com X-API-Version: 2 ``` ```http GET /api/users HTTP/1.1 Host: example.com X-API-Version: v2 ``` -------------------------------- ### Multi-Domain URI Routing Example Requests Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Example HTTP requests demonstrating how multiple domains can serve the same API version. ```http GET /v1/users HTTP/1.1 Host: api.main.com GET /v1/users HTTP/1.1 Host: api.backup.com GET /v1/users HTTP/1.1 Host: api.proxy.com ``` -------------------------------- ### URI Path Strategy Example Request Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Example HTTP requests demonstrating the URI path strategy for different API versions. ```http GET /api/v1/users HTTP/1.1 Host: example.com ``` ```http GET /api/v2/users HTTP/1.1 Host: example.com ``` -------------------------------- ### Accept Header Strategy Example Request Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Example HTTP request using the Accept header with content negotiation to specify the API version. ```http GET /api/users HTTP/1.1 Host: example.com Accept: application/vnd.api.v2+json ``` -------------------------------- ### Accept Header Strategy with Custom Vendor Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Example HTTP request demonstrating the Accept header strategy with a custom vendor name. ```http GET /api/users HTTP/1.1 Host: example.com Accept: application/vnd.mycompany.v2+json ``` -------------------------------- ### Query Parameter Strategy Example Request Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Example HTTP request using the 'api_version' query parameter to specify the API version. ```http GET /api/users?api_version=2 HTTP/1.1 Host: example.com ``` -------------------------------- ### VersionSunsetException Response Source: https://github.com/grazulex/laravel-apiroute/wiki/Exceptions Example JSON response for a VersionSunsetException, indicating the error, a message, sunset date, successor version, and migration guide URL. ```json { "error": "api_version_sunset", "message": "API version v1 is no longer available.", "sunset_date": "2024-12-01T00:00:00+00:00", "successor": "v2", "migration_guide": "https://docs.example.com/migration/v1-to-v2" } ``` -------------------------------- ### Verify Laravel ApiRoute Installation Source: https://github.com/grazulex/laravel-apiroute/wiki/Installation Run this command to confirm the package is installed correctly. Expected output is 'No API versions registered.' ```bash php artisan api:status ``` -------------------------------- ### Subdomain-Based URI Routing Example Requests Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Example HTTP requests for API versions served from a dedicated subdomain. ```http GET /v1/users HTTP/1.1 Host: api.example.com ``` ```http GET /v2/users HTTP/1.1 Host: api.example.com ``` -------------------------------- ### Complete Deprecated API Version Example Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers This PHP example configures a deprecated API version with deprecation, sunset, and successor information, demonstrating the generation of multiple RFC-compliant headers. ```php ApiRoute::version('v1', function () { Route::get('users', [UserController::class, 'index']); }) ->deprecated('2025-06-01') ->sunset('2025-12-01') ->setSuccessor('v2'); ``` -------------------------------- ### Setup Simple Multi-Version API Source: https://github.com/grazulex/laravel-apiroute/wiki/Examples Defines a simple API with version 1 and sets it as the current version. Requires importing ApiRoute facade and Illuminate Support Facades Route. ```php // routes/api.php use Grazulex\ApiRoute\Facades\ApiRoute; use Illuminate\Support\Facades\Route; // Version 1 ApiRoute::version('v1', function () { Route::get('users', function () { return response()->json([ 'users' => [ ['id' => 1, 'name' => 'John'], ['id' => 2, 'name' => 'Jane'], ] ]); }); })->current(); ``` -------------------------------- ### Complete API Version Declaration Example Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Demonstrates defining multiple API versions with various lifecycle states (deprecated, current, beta) and configurations like documentation URLs, rate limits, and middleware. ```php use Grazulex\ApiRoute\Facades\ApiRoute; use Illuminate\Support\Facades\Route; // Version 1 - Deprecated, will be sunset ApiRoute::version('v1', function () { Route::apiResource('users', App\Http\Controllers\Api\V1\UserController::class); Route::apiResource('posts', App\Http\Controllers\Api\V1\PostController::class); }) ->deprecated('2025-06-01') ->sunset('2025-12-01') ->setSuccessor('v2') ->documentation('https://docs.myapp.com/api/v1') ->rateLimit(100); // Version 2 - Current stable version ApiRoute::version('v2', function () { Route::apiResource('users', App\Http\Controllers\Api\V2\UserController::class); Route::apiResource('posts', App\Http\Controllers\Api\V2\PostController::class); Route::apiResource('comments', App\Http\Controllers\Api\V2\CommentController::class); }) ->current() ->documentation('https://docs.myapp.com/api/v2') ->rateLimit(1000); // Version 3 - Beta preview ApiRoute::version('v3', function () { Route::apiResource('users', App\Http\Controllers\Api\V3\UserController::class); }) ->beta() ->documentation('https://docs.myapp.com/api/v3-beta') ->middleware(['auth:sanctum']); ``` -------------------------------- ### Registering API Route with Name in v1 Source: https://github.com/grazulex/laravel-apiroute/wiki/Migration-v1-to-v2 Define route names within your API route files. This example shows how to name a GET route for users in v1. ```php // routes/api/v1.php Route::get('users', [UserController::class, 'index'])->name('api.v1.users.index'); ``` -------------------------------- ### Define API v1 Routes Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Example of defining routes for API version 1 in a dedicated PHP file. ```php setSuccessor('v2') ->documentation('https://docs.example.com/migration/v1-to-v2') ``` -------------------------------- ### Example API Response Headers Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers This example shows the typical HTTP headers automatically added to an API response, including versioning and lifecycle information. ```http HTTP/1.1 200 OK X-API-Version: v1 X-API-Version-Status: deprecated Deprecation: Sun, 01 Jun 2025 00:00:00 GMT Sunset: Mon, 01 Dec 2025 00:00:00 GMT Link: ; rel="successor-version" ``` -------------------------------- ### Complete E-Commerce API Setup with Multiple Versions Source: https://github.com/grazulex/laravel-apiroute/wiki/Examples Sets up multiple API versions (v1, v2, v3) for an e-commerce platform, including route definitions, deprecation, sunsetting, successor versions, documentation links, rate limiting, and middleware. Version 2 is marked as current, and v3 is in beta. ```php // routes/api.php use Grazulex\ApiRoute\Facades\ApiRoute; use Illuminate\Support\Facades\Route; // Version 1 - Legacy (deprecated) ApiRoute::version('v1', function () { Route::apiResource('products', App\Http\Controllers\Api\V1\ProductController::class); Route::apiResource('orders', App\Http\Controllers\Api\V1\OrderController::class); Route::apiResource('customers', App\Http\Controllers\Api\V1\CustomerController::class); }) ->deprecated('2025-06-01') ->sunset('2025-12-01') ->setSuccessor('v2') ->documentation('https://api.myshop.com/docs/v1') ->rateLimit(100); // Version 2 - Current ApiRoute::version('v2', function () { Route::apiResource('products', App\Http\Controllers\Api\V2\ProductController::class); Route::apiResource('orders', App\Http\Controllers\Api\V2\OrderController::class); Route::apiResource('customers', App\Http\Controllers\Api\V2\CustomerController::class); // New endpoints in v2 Route::get('products/{product}/reviews', [App\Http\Controllers\Api\V2\ProductController::class, 'reviews']); Route::post('orders/{order}/refund', [App\Http\Controllers\Api\V2\OrderController::class, 'refund']); }) ->current() ->documentation('https://api.myshop.com/docs/v2') ->rateLimit(1000); // Version 3 - Beta ApiRoute::version('v3', function () { Route::apiResource('products', App\Http\Controllers\Api\V3\ProductController::class); // New GraphQL-like endpoint Route::post('query', App\Http\Controllers\Api\V3\QueryController::class); }) ->beta() ->documentation('https://api.myshop.com/docs/v3-beta') ->middleware(['auth:sanctum']); ``` -------------------------------- ### VersionNotFoundException Response Source: https://github.com/grazulex/laravel-apiroute/wiki/Exceptions Example JSON response for a VersionNotFoundException, indicating the error, a message, the requested version, and available versions. ```json { "error": "version_not_found", "message": "API version 'v99' not found.", "requested_version": "v99", "available_versions": ["v1", "v2", "v3"] } ``` -------------------------------- ### ApiRoute Sunset Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Exceptions Configuration example for handling sunset API versions. The 'action' must be set to 'reject' for VersionSunsetException to be thrown. ```php // config/apiroute.php 'sunset' => [ 'action' => 'reject', // Only throws when 'reject' 'status_code' => 410, ], ``` -------------------------------- ### Configure Sunset Action (Warn/Reject) Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Lifecycle Implement a gradual transition for version sunsets by configuring the `action` for the 'sunset' phase. You can start with a 'warn' action to notify users before moving to a 'reject' action to block requests. ```php // Phase 1: Warn users 'sunset' => ['action' => 'warn'], // Phase 2: Reject requests 'sunset' => ['action' => 'reject'], ``` -------------------------------- ### Complete Configuration Example Source: https://github.com/grazulex/laravel-apiroute/wiki/Configuration This is a full configuration array for the Laravel API Route package. It covers versioning strategies, default versions, fallback mechanisms, sunset policies, header inclusions, usage tracking, documentation URLs, and middleware settings. ```php 'uri', 'strategies' => [ 'uri' => [ 'prefix' => 'api', 'pattern' => 'v{version}', ], 'header' => [ 'name' => 'X-API-Version', ], 'query' => [ 'parameter' => 'api_version', ], 'accept' => [ 'pattern' => 'application/vnd.{vendor}.{version}+json', 'vendor' => 'myapp', ], ], 'default_version' => 'latest', 'fallback' => [ 'enabled' => true, 'strategy' => 'previous', 'add_header' => true, ], 'sunset' => [ 'action' => 'reject', 'status_code' => 410, 'include_migration_url' => true, ], 'headers' => [ 'enabled' => true, 'include' => [ 'version' => true, 'status' => true, 'deprecation' => true, 'sunset' => true, 'successor_link' => true, ], ], 'tracking' => [ 'enabled' => true, 'driver' => 'database', 'table' => 'api_version_stats', 'aggregate' => 'hourly', ], 'documentation' => [ 'base_url' => 'https://docs.myapp.com/api', 'migration_guides' => [ 'v1' => 'https://docs.myapp.com/api/migration/v1-to-v2', ], ], 'middleware' => [ 'group' => 'api', 'alias' => 'api.version', ], ]; ``` -------------------------------- ### Create API Version Route File (v2.0) Source: https://github.com/grazulex/laravel-apiroute/wiki/Migration-v1-to-v2 Create dedicated route files for each API version, for example, `routes/api/v1.php`. This organizes routes by version. ```php // routes/api/v1.php [ 'base_url' => env('API_DOCS_URL'), 'migration_guides' => [ // 'v1' => 'https://docs.example.com/api/migration/v1-to-v2', ], ], ``` -------------------------------- ### Create API Route File Source: https://github.com/grazulex/laravel-apiroute/blob/main/README.md Create separate route files for each API version, for example, `routes/api/v2.php`. This allows for organized routing per version. ```php // routes/api/v2.php use Illuminate\Support\Facades\Route; Route::apiResource('users', App\Http\Controllers\Api\V2\UserController::class); ``` -------------------------------- ### Legacy Fluent API: Declare Version v1 Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Example of declaring an API version using the legacy fluent API directly in `routes/api.php`. ```php use Grazulex\ApiRoute\Facades\ApiRoute; use Illuminate\Support\Facades\Route; ApiRoute::version('v1', function () { Route::get('users', [UserController::class, 'index']); Route::post('users', [UserController::class, 'store']); }); ``` -------------------------------- ### Implement Custom Version Resolver in PHP Source: https://github.com/grazulex/laravel-apiroute/wiki/Advanced-Usage Create a custom resolver for complex version detection logic by implementing the VersionResolverInterface. This example prioritizes version detection from headers, query parameters, URI, and user preferences. ```php getRequestedVersion($request); if ($version === null) { return $this->getDefaultVersion(); } return $this->manager->getVersion($version); } public function getRequestedVersion(Request $request): ?string { // Priority: Header > Query > URI > User preference return $request->header('X-API-Version') ?? $request->query('api_version') ?? $this->extractFromUri($request) ?? $this->getUserPreferredVersion($request); } private function extractFromUri(Request $request): ?string { if (preg_match('/\/api\/(v\d+)\/', $request->path(), $matches)) { return $matches[1]; } return null; } private function getUserPreferredVersion(Request $request): ?string { // Get user's preferred version from database $user = $request->user(); return $user?->preferred_api_version; } private function getDefaultVersion(): ?VersionDefinition { return $this->manager->currentVersion(); } } ``` -------------------------------- ### X-API-Version-Status Header Example Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers This header shows the lifecycle status of the API version. Possible values include active, beta, deprecated, and sunset. ```http X-API-Version-Status: active ``` -------------------------------- ### Redis Driver Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Usage-Tracking Configure the tracking to use the 'redis' driver for high-performance statistics storage. Requires Redis to be installed and configured. ```php 'tracking' => [ 'driver' => 'redis', ], ``` -------------------------------- ### Implement Custom Usage Tracker in PHP Source: https://github.com/grazulex/laravel-apiroute/wiki/Advanced-Usage Integrate with external analytics services by implementing the VersionTrackerInterface. This example sends API request data to an analytics service for tracking and querying. ```php analytics->track('api_request', [ 'version' => $version, 'endpoint' => $endpoint, 'method' => $method, 'status' => $status, 'success' => $status >= 200 && $status < 400, 'timestamp' => now()->toIso8601String(), ]); } public function getStats(string $version, int $days): array { return $this->analytics->query('api_request', [ 'version' => $version, 'from' => now()->subDays($days), 'to' => now(), ]); } public function getAllStats(int $days): array { return $this->analytics->query('api_request', [ 'from' => now()->subDays($days), 'to' => now(), 'groupBy' => 'version', ]); } } ``` -------------------------------- ### Custom URI Path Pattern Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Customize the URI pattern for versioning, for example, to use a different prefix like 'service'. ```php 'strategies' => [ 'uri' => [ 'prefix' => 'service', // /service/v1/users 'pattern' => 'v{version}', ], ], ``` -------------------------------- ### X-API-Version Header Example Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers This HTTP header indicates the current API version being used in the response. It is always present when headers are enabled. ```http X-API-Version: v1 ``` -------------------------------- ### VersionHeaders Class Example Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers Illustrates the VersionHeaders class, which is responsible for adding version-related headers to responses. This class is typically used internally by middleware. ```php use Grazulex\ApiRoute\Http\Headers\VersionHeaders; class VersionHeaders { public function addToResponse(Response $response, VersionDefinition $version): Response { // Adds all configured headers } } ``` -------------------------------- ### Setting up API Versions in Laravel Tests Source: https://github.com/grazulex/laravel-apiroute/wiki/Advanced-Usage Demonstrates how to use the ApiVersionTestHelpers trait to configure API versions, including deprecation and sunset dates, within a Laravel test case. This setup is crucial for testing version-specific behaviors. ```php use Tests\Helpers\ApiVersionTestHelpers; class ApiVersionTest extends TestCase { use ApiVersionTestHelpers; protected function setUp(): void { parent::setUp(); $this->setupVersions([ 'v1' => [ 'routes' => fn() => Route::get('test', fn() => 'v1'), 'deprecated' => '2025-06-01', 'sunset' => '2025-12-01', ], 'v2' => [ 'routes' => fn() => Route::get('test', fn() => 'v2'), 'current' => true, ], ]); } public function test_v1_has_deprecation_headers(): void { $response = $this->apiGet('v1', 'test'); $response->assertOk(); $this->assertDeprecationHeaders($response); } } ``` -------------------------------- ### Define API Versions with Lifecycle States Source: https://github.com/grazulex/laravel-apiroute/wiki/Home Define different API versions using the ApiRoute facade. Specify version names, associate routes, and manage their lifecycle states like deprecated, sunset, current, or beta. This example shows how to define v1 (deprecated and sunset), v2 (current), and v3 (beta) versions with their respective routes and lifecycle dates. ```php use Grazulex\ApiRoute\Facades\ApiRoute; // Version 1 - Deprecated, sunset planned ApiRoute::version('v1', function () { Route::apiResource('users', UserController::class); }) ->deprecated('2025-06-01') ->sunset('2025-12-01'); // Version 2 - Current stable version ApiRoute::version('v2', function () { Route::apiResource('users', UserController::class); })->current(); // Version 3 - Beta/Preview ApiRoute::version('v3', function () { Route::apiResource('users', UserController::class); })->beta(); ``` -------------------------------- ### Create API Route File Source: https://github.com/grazulex/laravel-apiroute/wiki/Getting-Started Create a directory and a route file for your API version. ```bash mkdir -p routes/api touch routes/api/v1.php ``` -------------------------------- ### Publish and Run API Route Migrations Source: https://github.com/grazulex/laravel-apiroute/wiki/Usage-Tracking Publish the necessary migration files for API route tracking and then run the migrations to create the database table. ```bash php artisan vendor:publish --tag="apiroute-migrations" php artisan migrate ``` -------------------------------- ### Configure Accept Header Strategy Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Set the strategy to 'accept' and define the pattern and vendor for content negotiation in the Accept header. ```php // config/apiroute.php 'strategy' => 'accept', 'strategies' => [ 'accept' => [ 'pattern' => 'application/vnd.{vendor}.{version}+json', 'vendor' => env('API_VENDOR', 'api'), ], ], ``` -------------------------------- ### InvalidVersionException Response Source: https://github.com/grazulex/laravel-apiroute/wiki/Exceptions Example JSON response for an InvalidVersionException, indicating the error and the invalid version format. ```json { "error": "invalid_version", "message": "Invalid API version format: 'invalid'" } ``` -------------------------------- ### Install Laravel ApiRoute via Composer Source: https://github.com/grazulex/laravel-apiroute/wiki/Installation Use Composer to add the Laravel ApiRoute package to your project dependencies. ```bash composer require grazulex/laravel-apiroute ``` -------------------------------- ### Fluent API: Mark Version as Beta Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Using the fluent API to define API version v3 and mark it as a beta/preview version. ```php ApiRoute::version('v3', function () { Route::apiResource('users', UserController::class); })->beta(); ``` -------------------------------- ### Define API Route Source: https://github.com/grazulex/laravel-apiroute/wiki/Getting-Started Add a simple GET route for users to your API version's route file. ```php json(['message' => 'API v1']); }); ``` -------------------------------- ### Enable API Version Tracking via Environment Variable Source: https://github.com/grazulex/laravel-apiroute/wiki/Usage-Tracking Alternatively, enable tracking by setting the `API_VERSION_TRACKING` environment variable to `true` in your `.env` file. ```bash # .env API_VERSION_TRACKING=true ``` -------------------------------- ### Output API Status as JSON Source: https://github.com/grazulex/laravel-apiroute/wiki/Artisan-Commands Get the API status information in JSON format, which is useful for scripting and automated processes. ```bash php artisan api:status --json ``` -------------------------------- ### Configure URI Path Strategy Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Set the default strategy to 'uri' and define the prefix and pattern for versioned URLs in the configuration file. ```php // config/apiroute.php 'strategy' => 'uri', 'strategies' => [ 'uri' => [ 'prefix' => 'api', // /api/v1/users 'pattern' => 'v{version}', // v1, v2, etc. ], ], ``` -------------------------------- ### Organize Version-Specific Controllers Source: https://github.com/grazulex/laravel-apiroute/wiki/Getting-Started Structure your controllers within version-specific subdirectories for better organization. ```bash app/Http/Controllers/Api/ ├── V1/ │ └── UserController.php ├── V2/ │ └── UserController.php └── V3/ └── UserController.php ``` -------------------------------- ### Configure API Domains via Environment Variable Source: https://github.com/grazulex/laravel-apiroute/wiki/Configuration Dynamically configure API domains using an environment variable for flexible deployment. The domains are provided as a comma-separated list. ```php 'strategies' => [ 'uri' => [ 'prefix' => '', 'domain' => array_filter( array_map('trim', explode(',', env('API_DOMAINS', ''))) ), ], ], ``` ```env # .env API_DOMAINS=api.main.com,api.backup.com,api.proxy.com ``` -------------------------------- ### Enable API Version Tracking Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Usage-Tracking Configure tracking settings in the `config/apiroute.php` file. Set `enabled` to true to activate tracking. ```php // config/apiroute.php 'tracking' => [ 'enabled' => env('API_VERSION_TRACKING', true), 'driver' => 'database', 'table' => 'api_version_stats', 'aggregate' => 'hourly', ], ``` -------------------------------- ### Global Exception Handler for VersionNotFoundException Source: https://github.com/grazulex/laravel-apiroute/wiki/Exceptions Example of configuring a global exception handler in Laravel 11+ to render a custom JSON response for VersionNotFoundException. ```php use Grazulex\ApiRoute\Exceptions\VersionNotFoundException; use Grazulex\ApiRoute\Exceptions\VersionSunsetException; ->withExceptions(function (Exceptions $exceptions) { $exceptions->render(function (VersionNotFoundException $e, Request $request) { return response()->json([ 'error' => 'version_not_found', 'message' => $e->getMessage(), 'help' => 'Visit /api/versions for available versions', ], 404); }); $exceptions->render(function (VersionSunsetException $e, Request $request) { // Custom sunset response return response()->json([ 'error' => 'api_version_sunset', 'message' => 'Please upgrade to a newer API version', 'upgrade_url' => 'https://docs.example.com/upgrade', ], 410); }); }) ``` -------------------------------- ### X-API-Version-Fallback Header Example Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers This header is added when a request for one API version results in a response from a different version, indicating a fallback occurred. ```http X-API-Version: v2 X-API-Version-Fallback: v1 ``` -------------------------------- ### Configure Accept Header Strategy Source: https://github.com/grazulex/laravel-apiroute/wiki/Configuration Customize the Accept header strategy with a custom pattern and vendor name. ```php 'strategies' => [ 'accept' => [ 'pattern' => 'application/vnd.{vendor}.{version}+json', 'vendor' => env('API_VENDOR', 'api'), ], ], ``` -------------------------------- ### Controller Structure for API Versions Source: https://github.com/grazulex/laravel-apiroute/wiki/Examples Illustrates the directory structure for API controllers across different versions (V1, V2, V3). ```text app/Http/Controllers/Api/ ├── V1/ │ ├── ProductController.php │ ├── OrderController.php │ └── CustomerController.php ├── V2/ │ ├── ProductController.php │ ├── OrderController.php │ └── CustomerController.php └── V3/ ├── ProductController.php └── QueryController.php ``` -------------------------------- ### Custom API Version Middleware Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers Provides an example of extending the ResolveApiVersion middleware to add custom headers to the response. This is useful for implementing application-specific header logic. ```php use Grazulex\ApiRoute\Middleware\ResolveApiVersion; class CustomApiVersionMiddleware extends ResolveApiVersion { public function handle(Request $request, Closure $next): Response { $response = parent::handle($request, $next); // Add custom headers $response->headers->set('X-Custom-Header', 'value'); return $response; } } ``` -------------------------------- ### Define API Versions Source: https://github.com/grazulex/laravel-apiroute/wiki/Configuration Configure different API versions directly in the config file. This is recommended for proper registration on application boot. ```php 'versions' => [ 'v1' => [ 'routes' => base_path('routes/api/v1.php'), 'middleware' => ['auth:sanctum'], 'status' => 'deprecated', 'deprecated_at' => '2025-06-01', 'sunset_at' => '2025-12-01', 'successor' => 'v2', 'documentation' => 'https://docs.myapp.com/api/v1', 'rate_limit' => 100, ], 'v2' => [ 'routes' => base_path('routes/api/v2.php'), 'middleware' => ['auth:sanctum'], 'status' => 'active', 'documentation' => 'https://docs.myapp.com/api/v2', 'rate_limit' => 1000, ], ], ``` -------------------------------- ### Link Header for Successor Version Example Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers The Link header points to the successor API version, following RFC 8288. It is added when a successor version is defined. ```http Link: ; rel="successor-version" ``` -------------------------------- ### Automatic Deprecation Headers Example Source: https://github.com/grazulex/laravel-apiroute/blob/main/README.md When a version is deprecated, responses automatically include RFC-compliant `Deprecation` and `Sunset` headers, along with a `Link` header to the successor version. ```http HTTP/1.1 200 OK Deprecation: Sun, 01 Jun 2025 00:00:00 GMT Sunset: Mon, 01 Dec 2025 00:00:00 GMT Link: ; rel="successor-version" X-API-Version: v1 X-API-Version-Status: deprecated ``` -------------------------------- ### Fluent API: Set Rate Limits for Versions Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Demonstrates setting different rate limits for API versions v1 (deprecated) and v2 (current) using the fluent API. ```php // Lower rate limit for deprecated version ApiRoute::version('v1', function () { // ... }) ->deprecated('2025-06-01') ->rateLimit(100); // 100 requests/minute // Higher rate limit for current version ApiRoute::version('v2', function () { // ... }) ->current() ->rateLimit(1000); // 1000 requests/minute ``` -------------------------------- ### Deprecation Header (RFC 8594) Example Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers The Deprecation header indicates when an API version was deprecated, formatted according to RFC 7231 HTTP-date. It is only added for deprecated versions. ```http Deprecation: Sun, 01 Jun 2025 00:00:00 GMT ``` -------------------------------- ### Show Specific API Version Details Source: https://github.com/grazulex/laravel-apiroute/wiki/Artisan-Commands Retrieve detailed information for a particular API version, including its properties and route list. ```bash php artisan api:status --api-version=v1 ``` -------------------------------- ### Scaffold New API Version Source: https://github.com/grazulex/laravel-apiroute/wiki/Getting-Started Use the Artisan command to create a new API version, optionally copying from an existing one. ```bash php artisan api:version v2 # Copy from existing version php artisan api:version v2 --copy-from=v1 ``` -------------------------------- ### Register API Version (v2.0 - Recommended Configuration) Source: https://github.com/grazulex/laravel-apiroute/wiki/Migration-v1-to-v2 v2.0 recommends configuration-based version registration. Versions are defined in `config/apiroute.php`, ensuring they are properly registered on application boot. ```php // config/apiroute.php 'versions' => [ 'v1' => [ 'routes' => base_path('routes/api/v1.php'), 'middleware' => ['auth:sanctum'], 'status' => 'active', ], ], ``` ```php // routes/api/v1.php Route::get('users', [UserController::class, 'index']); ``` -------------------------------- ### Sunset Header (RFC 7231) Example Source: https://github.com/grazulex/laravel-apiroute/wiki/HTTP-Headers The Sunset header indicates when an API version will be removed, formatted according to RFC 7231 HTTP-date. It is added for versions with a defined sunset date. ```http Sunset: Mon, 01 Dec 2025 00:00:00 GMT ``` -------------------------------- ### Manually Register Facade Source: https://github.com/grazulex/laravel-apiroute/wiki/Installation If needed, manually add the `ApiRoute` facade to your `config/app.php` aliases. ```php 'aliases' => [ // ... 'ApiRoute' => Grazulex\ApiRoute\Facades\ApiRoute::class, ], ``` -------------------------------- ### Use Legacy Approach in Tests (v2.0) Source: https://github.com/grazulex/laravel-apiroute/wiki/Migration-v1-to-v2 If the legacy `ApiRoute::version()` approach must be used in tests, reset the manager and re-register versions within the test setup to ensure persistence. ```php beforeEach(function () { // Reset the manager app(ApiRouteManager::class)->reset(); // Re-register versions ApiRoute::version('v1', function () { Route::get('test', fn () => response()->json(['ok' => true])); })->current(); // Boot to apply config versions (if any) app(ApiRouteManager::class)->boot(); }); ``` -------------------------------- ### Use Custom API Error Response for Sunset Version Source: https://github.com/grazulex/laravel-apiroute/wiki/Exceptions Utilize the custom ApiErrorResponse to format the response for a sunset API version, including additional details like successor version and migration guide. ```php $exceptions->render(function (VersionSunsetException $e, Request $request) { return ApiErrorResponse::make( error: 'api_version_sunset', message: $e->getMessage(), status: 410, extra: [ 'successor' => $e->version->successor(), 'migration_guide' => config("apiroute.documentation.migration_guides.{$e->version->name()}"), ] ); }); ``` -------------------------------- ### Run All Composer Tests Source: https://github.com/grazulex/laravel-apiroute/blob/main/README.md Execute all defined tests using Composer. ```bash composer test ``` -------------------------------- ### Scaffold New API Version Source: https://github.com/grazulex/laravel-apiroute/wiki/Artisan-Commands Create a new API version by scaffolding its controller structure. This command generates the necessary files and directories. ```bash php artisan api:version v3 ``` -------------------------------- ### Fluent API: Mark Version as Current Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Using the fluent API to define API version v2 and mark it as the current stable version. ```php ApiRoute::version('v2', function () { Route::apiResource('users', UserController::class); })->current(); ``` -------------------------------- ### Accessing API Version Information via Facade Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Retrieve and manage API version definitions and status using the ApiRoute facade. Includes methods for getting all versions, specific versions, the current version, and checking existence. ```php use Grazulex\ApiRoute\Facades\ApiRoute; // Get all versions $versions = ApiRoute::versions(); // Collection // Get specific version $v1 = ApiRoute::getVersion('v1'); // ?VersionDefinition // Get current version $current = ApiRoute::currentVersion(); // ?VersionDefinition // Check if version exists if (ApiRoute::hasVersion('v2')) { // ... } // Status checks ApiRoute::isDeprecated('v1'); // bool ApiRoute::isSunset('v1'); // bool ApiRoute::isActive('v2'); // bool // Resolve version from request $version = ApiRoute::resolveVersion(request()); // string ``` -------------------------------- ### Database Driver Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Usage-Tracking Configure the tracking to use the 'database' driver, specifying the table name for storing statistics. ```php 'tracking' => [ 'driver' => 'database', 'table' => 'api_version_stats', ], ``` -------------------------------- ### Fluent API: Set Documentation URL Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Declaration Using the fluent API to associate a documentation URL with API version v1. ```php ApiRoute::version('v1', function () { // ... })->documentation('https://docs.example.com/api/v1'); ``` -------------------------------- ### View API Statistics via Command Line Source: https://github.com/grazulex/laravel-apiroute/wiki/Usage-Tracking Use the `php artisan api:stats` command to view API version usage statistics. Options include specifying a period, API version, or output format. ```bash # All versions (last 30 days) php artisan api:stats # Specific period php artisan api:stats --period=7 # Specific version php artisan api:stats --api-version=v1 # JSON output php artisan api:stats --json ``` -------------------------------- ### Different Authentication for API Versions Source: https://github.com/grazulex/laravel-apiroute/wiki/Examples Shows how to apply different authentication middleware to different API versions, such as basic API key auth for v1, Sanctum tokens for v2, and OAuth 2.0 for v3. ```php // Version 1 - Basic API key auth ApiRoute::version('v1', function () { Route::apiResource('users', App\Http\Controllers\Api\V1\UserController::class); }) ->middleware(['auth.apikey']); // Version 2 - Sanctum tokens ApiRoute::version('v2', function () { Route::apiResource('users', App\Http\Controllers\Api\V2\UserController::class); }) ->middleware(['auth:sanctum']); // Version 3 - OAuth 2.0 ApiRoute::version('v3', function () { Route::apiResource('users', App\Http\Controllers\Api\V3\UserController::class); }) ->middleware(['auth:passport']); ``` -------------------------------- ### Process JSON Command Output Source: https://github.com/grazulex/laravel-apiroute/wiki/Artisan-Commands Demonstrates how to pipe the JSON output of API commands to tools like `jq` for scripting and data processing, or redirect it to a file. ```bash php artisan api:status --json | jq '.[] | select(.status == "deprecated")' ``` ```bash php artisan api:stats --json > api-stats.json ``` -------------------------------- ### Configure Header Detection Strategy Source: https://github.com/grazulex/laravel-apiroute/wiki/Configuration Customize the header detection strategy by specifying the header name. ```php 'strategies' => [ 'header' => [ 'name' => 'X-API-Version', ], ], ``` -------------------------------- ### Version-Aware Controller Logic Source: https://github.com/grazulex/laravel-apiroute/wiki/Examples Demonstrates how to check the API version within a controller and implement version-specific behavior, such as logging for deprecated versions and including version-specific data. ```php isDeprecatedVersion()) { // Log for migration tracking logger()->warning('Deprecated API version used', [ 'version' => $request->apiVersion(), 'endpoint' => $request->path(), 'user' => $request->user()?->id, ]); } // Add v2-specific includes $products->with(['category', 'brand', 'reviews']); return response()->json([ 'data' => $products->paginate(20), 'meta' => [ 'api_version' => $request->apiVersion(), ], ]); } } ``` -------------------------------- ### Republish Configuration (v2.0) Source: https://github.com/grazulex/laravel-apiroute/wiki/Migration-v1-to-v2 If the configuration was previously published, republish it using `php artisan vendor:publish --tag="apiroute-config" --force` to ensure the latest version is used, then merge existing settings. ```bash php artisan vendor:publish --tag="apiroute-config" --force ``` -------------------------------- ### Configure Header Strategy Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Set the strategy to 'header' and specify the custom header name used for API versioning. ```php // config/apiroute.php 'strategy' => 'header', 'strategies' => [ 'header' => [ 'name' => 'X-API-Version', // Header name ], ], ``` -------------------------------- ### Configure URI Detection Strategy Source: https://github.com/grazulex/laravel-apiroute/wiki/Configuration Customize the URI detection strategy, including URL prefix, version pattern, and optional subdomain. ```php 'strategies' => [ 'uri' => [ 'prefix' => 'api', 'pattern' => 'v{version}', 'domain' => null, ], ], ``` -------------------------------- ### Version Negotiation Service Source: https://github.com/grazulex/laravel-apiroute/wiki/Advanced-Usage Implement a service to negotiate the API version based on client capabilities, checking for exact matches in headers and falling back to supported versions or a default. ```php header('X-API-Version'); $supported = $this->parseAcceptVersions($request); $available = $this->manager->versions()->pluck('name')->toArray(); // Exact match if ($requested && in_array($requested, $available)) { return $requested; } // Find best match from Accept-Version header foreach ($supported as $version) { if (in_array($version, $available)) { return $version; } } // Default to current return $this->manager->currentVersion()?->name() ?? 'v1'; } private function parseAcceptVersions(Request $request): array { $header = $request->header('Accept-Version', ''); return array_filter(array_map('trim', explode(',', $header))); } } ``` -------------------------------- ### Request Legacy Endpoint via Fallback Source: https://github.com/grazulex/laravel-apiroute/wiki/Examples Demonstrates how to request a legacy endpoint that is not defined in the current API version (v2) but is available in a previous version (v1) due to the fallback strategy. ```bash curl http://localhost/api/v2/legacy-endpoint ``` -------------------------------- ### Sunset API Version via Artisan Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Lifecycle Uses the Artisan command to immediately sunset a specific API version. ```bash php artisan api:sunset v1 ``` -------------------------------- ### Dynamic Subdomain Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Configuration Use environment variables to dynamically set the API domain for different environments. ```php 'strategies' => [ 'uri' => [ 'prefix' => '', 'domain' => env('API_DOMAIN', 'api.example.com'), ], ], ``` -------------------------------- ### Alternative Header Names Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Configure alternative header names for API version detection, such as 'Api-Version' or a custom prefixed name. ```php 'strategies' => [ 'header' => [ 'name' => 'Api-Version', // Shorter name // or 'name' => 'X-My-App-Version', // Custom prefix ], ], ``` -------------------------------- ### Manually Register Service Provider Source: https://github.com/grazulex/laravel-apiroute/wiki/Installation If auto-discovery is disabled, manually add the service provider to your `config/app.php` file. ```php 'providers' => [ // ... Grazulex\ApiRoute\ApiRouteServiceProvider::class, ], ``` -------------------------------- ### Alternative Query Parameter Names Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Configure alternative query parameter names for API version detection, such as 'v' or 'version'. ```php 'strategies' => [ 'query' => [ 'parameter' => 'v', // Short: ?v=2 // or 'parameter' => 'version', // Explicit: ?version=2 ], ], ``` -------------------------------- ### Configure API Version Source: https://github.com/grazulex/laravel-apiroute/wiki/Getting-Started Add your API version configuration to `config/apiroute.php`, specifying the route file and status. ```php 'versions' => [ 'v1' => [ 'routes' => base_path('routes/api/v1.php'), 'status' => 'active', ], ], ``` -------------------------------- ### Custom Accept Strategy Pattern Source: https://github.com/grazulex/laravel-apiroute/wiki/Detection-Strategies Defines a custom pattern for the 'accept' strategy, allowing for vendor and version specific media types. ```php 'strategies' => [ 'accept' => [ 'pattern' => 'application/vnd.{vendor}.{version}+json', 'vendor' => 'mycompany', // application/vnd.mycompany.v2+json ], ], ``` -------------------------------- ### Define Beta API Version Source: https://github.com/grazulex/laravel-apiroute/wiki/Version-Lifecycle Designates a version as a preview for testing new features. It may contain breaking changes and is not recommended for production. ```php ApiRoute::version('v3', function () { Route::apiResource('users', UserController::class); })->beta(); ``` -------------------------------- ### Enable API Usage Tracking Configuration Source: https://github.com/grazulex/laravel-apiroute/wiki/Middleware Configure API usage tracking by setting `enabled` to `true` in the `config/apiroute.php` file. Specify the driver, table, and aggregation interval for tracking statistics. ```php // config/apiroute.php 'tracking' => [ 'enabled' => true, 'driver' => 'database', 'table' => 'api_version_stats', 'aggregate' => 'hourly', ], ``` -------------------------------- ### Configure Multiple Domains for API Routes Source: https://github.com/grazulex/laravel-apiroute/wiki/Configuration Set multiple domains for API routes to serve the same versioned routes, useful for resilience or redundancy scenarios. ```php 'strategies' => [ 'uri' => [ 'prefix' => '', 'pattern' => 'v{version}', 'domain' => ['api.main.com', 'api.backup.com', 'api.proxy.com'], ], ], ```