check24/apitk-deprecation-bundle
Installation:
composer require check24/apitk-deprecation-bundle
Ensure check24/apitk-deprecation-bundle is added to config/bundles.php if using Symfony Flex.
First Use Case:
Mark an existing API endpoint as deprecated in your controller using the @Deprecated annotation:
use Shopping\ApiTKDeprecationBundle\Annotation\Deprecated;
/**
x-apitk-deprecated header is included in the response.Gradual Deprecation Workflow:
@Deprecated(since="YYYY-MM-DD", description="...").removedAfter="YYYY-MM-DD" to inform clients of the final removal date.removedAfter date.Documentation Integration:
hideFromDocs=true to exclude deprecated endpoints from Swagger/OpenAPI docs while keeping them functional for existing clients.@Deprecated(hideFromDocs=true, description="Internal use only")
Batch Deprecation:
@Deprecated annotation to multiple endpoints in a single controller or service class for consistency./**
* @Rest\Get("/v1/users/{id}")
* @Deprecated(description="Use /v2/users/{id} instead")
*/
public function getUserAction($id) { ... }
/**
* @Rest\Post("/v1/users")
* @Deprecated(description="Use /v2/users instead")
*/
public function createUserAction() { ... }
Custom Deprecation Messages:
deprecated header value by providing a description in the annotation.@Deprecated(description="Endpoint retired. Contact support for migration assistance.")
API Versioning:
/v1/, /v2/) to clearly separate deprecated and active endpoints.@Rest\Get("/v1/legacy-data")
@Deprecated(removedAfter="2023-12-31", description="Use /v2/data instead")
Automated Testing:
x-apitk-deprecated header is included in responses for deprecated endpoints.public function testDeprecatedEndpointHeaders()
{
$response = $this->client->request('GET', '/v1/old-endpoint');
$this->assertEquals(
'Use /v2/new-endpoint instead',
$response->headers->get('x-apitk-deprecated')
);
}
Logging Deprecation Warnings:
public function oldEndpointAction()
{
\Log::warning('Deprecated endpoint called: /v1/old-endpoint');
// ...
}
Swagger UI Customization:
Annotation Parsing Issues:
nelmio/api-doc-bundle or equivalent bundle is installed and configured to parse annotations like @Deprecated. Without it, the deprecation headers won’t be added.nelmio_api_doc is enabled in config/bundles.php and annotations are processed.Header Overrides:
x-apitk-deprecated header. Ensure such middleware runs after the apitk-deprecation-bundle middleware.kernel.php or AppKernel.php:
$middleware->prepend(\Shopping\ApiTKDeprecationBundle\Middleware\DeprecationMiddleware::class);
Date Format Strictness:
since and removedAfter arguments must use the YYYY-MM-DD format. Invalid formats may cause parsing errors.Caching Headers:
x-apitk-deprecated header. Otherwise, clients may not see deprecation notices.x-apitk-deprecated.Annotation Placement:
@Deprecated annotation must be placed above the method or class it applies to. Placing it inside the method body or on properties will have no effect.Missing Headers:
config/bundles.php.dd() or var_dump() in the bundle’s middleware to confirm it’s being triggered.Swagger Docs Not Updating:
php bin/console nelmio:apidoc:generate
openapi.yaml or swagger.json for deprecation tags.Deprecated Endpoint Still Accessible:
removedAfter date has passed.throw new \RuntimeException('Deprecated endpoint called!'); to confirm the endpoint is still reachable.Consistent Naming:
/v1/old-* → /v2/new-*). This makes it easier for clients to migrate.Deprecation Timeline:
Client-Side Handling:
Monitor Adoption:
Extend the Bundle:
DeprecationMiddleware to log IP addresses or user agents:
namespace App\Middleware;
use Shopping\ApiTKDeprecationBundle\Middleware\DeprecationMiddleware as BaseMiddleware;
use Psr\Log\LoggerInterface;
class CustomDeprecationMiddleware extends BaseMiddleware
{
protected $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function handle($request, \Closure $next)
{
$response = parent::handle($request, $next);
if ($this->isDeprecated($request)) {
$this->logger->warning(
'Deprecated endpoint called by IP: ' . $request->getClientIp()
);
}
return $response;
}
}
Deprecation in Tests:
$this->client->getContainer()->get('apitk_deprecation.listener')->setDeprecatedEndpoints([]);
How can I help you explore Laravel packages today?