### Install macpaw/symfony-deprecated-routes Bundle Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Install the bundle using Composer. This command adds the package to your project's dependencies. ```bash composer require macpaw/symfony-deprecated-routes ``` -------------------------------- ### Install Dependencies with Composer Source: https://github.com/macpaw/symfony-deprecated-routes/blob/develop/AGENTS.md Use this command to install project dependencies. No composer.lock is committed, so this resolves the latest compatible versions each time. ```bash composer install ``` -------------------------------- ### Install Symfony Deprecated Routes Bundle Source: https://github.com/macpaw/symfony-deprecated-routes/blob/develop/README.md Use Composer to install the bundle. Ensure you are using the correct package name. ```shell composer require macpaw/symfony-messenger-bundle ``` -------------------------------- ### Configure Deprecated Routes Bundle Options Source: https://github.com/macpaw/symfony-deprecated-routes/blob/develop/README.md Example configuration for the deprecated-routes bundle, showing default values for headers and flags. This file should be placed at config/packages/deprecated-routes.yaml. ```yaml deprecated-routes: isSinceRequired: false isDisabled: false headers: deprecatedMessageName: 'X-DEPRECATED' deprecatedFromName: 'X-DEPRECATED-FROM' deprecatedSinceName: 'X-DEPRECATED-SINCE' ``` -------------------------------- ### Mark Controller Action as Deprecated Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Use the `#[DeprecatedRoute]` attribute on a controller action to specify a deprecation message, start date, and an optional removal date. This example shows method-level deprecation for a GET request. ```php json(['users' => []]); } // Method-level deprecation — no removal date (since is optional) #[Route('/api/v1/users/{id}', name: 'api_v1_user_get', methods: ['GET'])] #[DeprecatedRoute( message: 'Use /api/v2/users/{id}.', from: new DateTimeImmutable('2023-06-01'), )] public function getUserV1(int $id): JsonResponse { return $this->json(['id' => $id]); } } ``` -------------------------------- ### Deprecated Route Response Headers Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Example of HTTP response headers generated by the bundle when a deprecated route is accessed. These headers communicate deprecation information to API consumers. ```http HTTP/1.1 200 OK X-DEPRECATED: Use /api/v2/users instead. This endpoint will be removed. X-DEPRECATED-FROM: 2023-06-01 X-DEPRECATED-SINCE: 2024-12-31 ``` -------------------------------- ### Perform Static Analysis with PHPStan Source: https://github.com/macpaw/symfony-deprecated-routes/blob/develop/AGENTS.md Run static analysis at the maximum level to identify potential code issues. Excluded paths are configured in phpstan.neon. ```bash vendor/bin/phpstan analyse ``` -------------------------------- ### Process RouteCollection with MarkDeprecatedRoutes (Required Since) Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Instantiate MarkDeprecatedRoutes with `sinceOptionIsRequired` set to true to enforce the presence of a 'since' date for deprecated routes. Throws SinceHeaderRequiredException if missing. ```php add('api_v1_user_get', new Route( path: '/api/v1/users/{id}', defaults: ['_controller' => 'App\Controller\UserController::getUserV1'], )); try { $strictReader->updateRoutes($routesWithMissingSince); } catch (SinceHeaderRequiredException $e) { // Thrown because #[DeprecatedRoute] on getUserV1 has no `since` date echo 'Deprecation `since` date is required but missing.'; } ``` -------------------------------- ### Configure Deprecated Routes Bundle Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Customize header names, the global disable switch, and the requirement for a 'since' date in the bundle's configuration file. These settings can be overridden by environment variables. ```yaml # config/packages/deprecated_routes.yaml deprecated-routes: isDisabled: '%env(resolve:bool:DISABLE_DEPRECATION_ROUTES)%' # set true to suppress all headers isSinceRequired: false # set true to throw SinceHeaderRequiredException when #[DeprecatedRoute] has no `since` headers: deprecatedMessageName: 'X-DEPRECATED' # header carrying the deprecation message deprecatedFromName: 'X-DEPRECATED-FROM' # header carrying the deprecation start date deprecatedSinceName: 'X-DEPRECATED-SINCE' # header carrying the planned removal date ``` -------------------------------- ### Run Tests with PHPUnit Source: https://github.com/macpaw/symfony-deprecated-routes/blob/develop/AGENTS.md Execute the project's unit and functional tests using PHPUnit. The test kernel is located at Macpaw\SymfonyDeprecatedRoutes\Tests\App. ```bash vendor/bin/phpunit ``` -------------------------------- ### Instantiate and Use DeprecationRoutesEventSubscriber Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Manually instantiate the subscriber and simulate its usage with a request and response to inject deprecation headers. This is normally managed by the DI container. ```php attributes->set(MarkDeprecatedRoutes::DEPRECATED_OPTION, [ MarkDeprecatedRoutes::DEPRECATED_MESSAGE_OPTION => 'Use /api/v2/users instead.', MarkDeprecatedRoutes::DEPRECATED_FROM_OPTION => '2023-06-01', MarkDeprecatedRoutes::DEPRECATED_SINCE_OPTION => '2024-12-31', ]); $response = new Response(); $kernel = /* your HttpKernelInterface instance */; $event = new ResponseEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $response); $subscriber->onKernelResponse($event); // $response now carries: // X-DEPRECATED: Use /api/v2/users instead. // X-DEPRECATED-FROM: 2023-06-01 // X-DEPRECATED-SINCE: 2024-12-31 // Subscribed events var_dump(DeprecationRoutesEventSubscriber::getSubscribedEvents()); // ['kernel.response' => ['onKernelResponse', 200]] // Verify headers assert($response->headers->has('X-DEPRECATED')); assert($response->headers->get('X-DEPRECATED-FROM') === '2023-06-01'); assert($response->headers->get('X-DEPRECATED-SINCE') === '2024-12-31'); ``` -------------------------------- ### Process RouteCollection with MarkDeprecatedRoutes (Optional Since) Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Instantiate MarkDeprecatedRoutes with `sinceOptionIsRequired` set to false to process a RouteCollection. This adds deprecation metadata to route defaults. ```php add('api_v1_users', new Route( path: '/api/v1/users', defaults: ['_controller' => 'App\Controller\UserController::listUsersV1'], methods: [Request::METHOD_GET], )); $reader->updateRoutes($routes); $route = $routes->get('api_v1_users'); $defaults = $route->getDefaults(); // $defaults['DEPRECATED'] is now set: // [ // 'DEPRECATED_MESSAGE' => 'Use /api/v2/users instead.', // 'DEPRECATED_FROM' => '2023-06-01', // 'DEPRECATED_SINCE' => '2024-12-31', // null if not provided // ] ``` -------------------------------- ### Lint Code Style with PHPCS Source: https://github.com/macpaw/symfony-deprecated-routes/blob/develop/AGENTS.md Apply PSR-12 coding standards with custom rules to check code style. Configuration is defined in phpcs.xml.dist. ```bash vendor/bin/phpcs ``` -------------------------------- ### Validate Composer Configuration Source: https://github.com/macpaw/symfony-deprecated-routes/blob/develop/AGENTS.md Validate the composer.json file for correct syntax and structure. This command shadows the 'composer validate' command. ```bash composer validate ``` -------------------------------- ### Configure Deprecation Routes in .env.test Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Set DISABLE_DEPRECATION_ROUTES to true in your .env.test file to disable deprecation headers in test environments. ```env DISABLE_DEPRECATION_ROUTES=true ``` -------------------------------- ### Enable Deprecated Routes Bundle in Symfony Source: https://github.com/macpaw/symfony-deprecated-routes/blob/develop/README.md Enable the bundle by adding its class to the list of registered bundles in your config/bundles.php file. ```php // config/bundles.php return [ Macpaw\SymfonyDeprecatedRoutes\DeprecatedRoutesBundle::class => ['all' => true], // ... ]; ``` -------------------------------- ### Verify Headers Absent When Deprecation Routes Disabled Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt This functional test verifies that deprecation headers are not present in the response when DISABLE_DEPRECATION_ROUTES is set to true. ```php use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Macpaw\SymfonyDeprecatedRoutes\Routing\EventSubscriber\DeprecationRoutesEventSubscriber; class DeprecatedRouteTest extends WebTestCase { public function testHeadersAbsentWhenDisabled(): void { putenv('DISABLE_DEPRECATION_ROUTES=true'); $client = static::createClient(); $client->request('GET', '/api/v1/users'); $response = $client->getResponse(); self::assertFalse($response->headers->has(DeprecationRoutesEventSubscriber::X_DEPRECATED_HEADER)); self::assertFalse($response->headers->has(DeprecationRoutesEventSubscriber::X_DEPRECATED_FROM_HEADER)); self::assertFalse($response->headers->has(DeprecationRoutesEventSubscriber::X_DEPRECATED_SINCE_HEADER)); } public function testHeadersPresentWhenEnabled(): void { putenv('DISABLE_DEPRECATION_ROUTES=false'); $client = static::createClient(); $client->request('GET', '/api/v1/users'); $response = $client->getResponse(); self::assertTrue($response->headers->has(DeprecationRoutesEventSubscriber::X_DEPRECATED_HEADER)); self::assertEquals('Use /api/v2/users instead.', $response->headers->get(DeprecationRoutesEventSubscriber::X_DEPRECATED_HEADER)); self::assertEquals('2023-06-01', $response->headers->get(DeprecationRoutesEventSubscriber::X_DEPRECATED_FROM_HEADER)); self::assertEquals('2024-12-31', $response->headers->get(DeprecationRoutesEventSubscriber::X_DEPRECATED_SINCE_HEADER)); } } ``` -------------------------------- ### Disable Deprecation Headers via Environment Variable Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Suppress deprecation headers in specific environments like local development or test pipelines by setting the `DISABLE_DEPRECATION_ROUTES` environment variable to `true`. This configuration prevents the event subscriber from adding headers while keeping application logic unaffected. ```yaml # config/packages/deprecated_routes.yaml deprecated-routes: isDisabled: '%env(resolve:bool:DISABLE_DEPRECATION_ROUTES)%' ``` -------------------------------- ### Decorate Routes Loader with Deprecation Metadata Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Use `RoutesLoaderDecorator` to wrap Symfony's native routing loader. It intercepts the `RouteCollection` after loading and stamps deprecation metadata onto routes marked with `#[DeprecatedRoute]`. This ensures deprecation information is added at a single point without affecting runtime request handling. ```php supports('config/routes/api.yaml', 'yaml') === $innerLoader->supports('config/routes/api.yaml', 'yaml')); // load() runs the inner loader and then stamps deprecated routes /** @var RouteCollection $routes */ $routes = $decorator->load('config/routes/api.yaml', 'yaml'); // At this point all routes whose controllers carry #[DeprecatedRoute] // have their defaults enriched with DEPRECATED metadata. foreach ($routes->getIterator() as $name => $route) { $defaults = $route->getDefaults(); if (isset($defaults[MarkDeprecatedRoutes::DEPRECATED_OPTION])) { echo sprintf( "Route '%s' is deprecated since %s: %s\n", $name, $defaults[MarkDeprecatedRoutes::DEPRECATED_OPTION][MarkDeprecatedRoutes::DEPRECATED_FROM_OPTION], $defaults[MarkDeprecatedRoutes::DEPRECATED_OPTION][MarkDeprecatedRoutes::DEPRECATED_MESSAGE_OPTION], ); } } ``` -------------------------------- ### Handle Missing 'since' Date with SinceHeaderRequiredException Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Catch `SinceHeaderRequiredException` when loading routes if strict mode is enabled and a `#[DeprecatedRoute]` attribute is missing the `since` date. This exception is a subclass of `InvalidArgumentException`, allowing for broad or specific catching. Re-throw in CI or strict environments to fail the build. ```php load('config/routes/api.yaml'); } catch (SinceHeaderRequiredException $e) { // $e is an InvalidArgumentException — safe to catch broadly or specifically echo 'A deprecated route is missing its planned removal date (since).'; // In CI or strict environments, re-throw to fail the build: throw $e; } ``` -------------------------------- ### Mark Entire Controller Class as Deprecated Source: https://context7.com/macpaw/symfony-deprecated-routes/llms.txt Apply the `#[DeprecatedRoute]` attribute to a controller class to mark all its associated routes as deprecated. This is useful for deprecating an entire API version or feature set. ```php // Class-level deprecation — applies to all routes in an invokable controller #[DeprecatedRoute( message: 'This entire controller is deprecated.', from: new DateTimeImmutable('2023-01-01'), since: new DateTimeImmutable('2025-01-01'), )] final class LegacySearchController extends AbstractController { #[Route('/api/v1/search', name: 'api_v1_search', methods: ['GET'])] public function __invoke(): JsonResponse { return $this->json(['results' => []]); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.