create-api-versioning
API Versioning Generator
Creates API Versioning infrastructure with multiple resolution strategies and deprecation support.
When to Use
| Scenario | Example |
|---|---|
| Breaking API changes | New response format |
| Multiple API consumers | Mobile v1, web v2 |
| Gradual migration | Sunset old versions |
| Backward compatibility | Support legacy clients |
Component Characteristics
ApiVersion (Value Object)
- Immutable version representation
- Major and minor version numbers
- Comparison methods (equals, greaterThan, lessThan)
- String parsing (fromString "v1.2")
VersionResolverInterface
- Extracts version from PSR-7 request
- Returns null if version not found
- Strategy pattern for different sources
Resolution Strategies
- UriPrefixVersionResolver — Extracts from URI path (/v1/orders)
- AcceptHeaderVersionResolver — Extracts from Accept header (application/vnd.api.v1+json)
- QueryParamVersionResolver — Extracts from query string (?version=1)
- CompositeVersionResolver — Tries multiple strategies in order
VersionMiddleware
- PSR-15 middleware
- Resolves version via strategy
- Adds version to request attributes
- Returns 400 if version required but missing
Generation Process
Step 1: Generate Domain Components
Path: src/Domain/Shared/Api/
ApiVersion.php— Immutable version value objectVersionResolverInterface.php— Version resolution contract
Step 2: Generate Presentation Components
Path: src/Presentation/Middleware/
UriPrefixVersionResolver.php— URI path strategyAcceptHeaderVersionResolver.php— Content negotiation strategyQueryParamVersionResolver.php— Query parameter strategyCompositeVersionResolver.php— Composite strategyVersionMiddleware.php— PSR-15 middlewareDeprecationHeaderMiddleware.php— Deprecation/Sunset headers
Step 3: Generate Tests
ApiVersionTest.php— Value object testsUriPrefixVersionResolverTest.php— URI parsing testsAcceptHeaderVersionResolverTest.php— Header parsing testsVersionMiddlewareTest.php— Middleware behavior tests
File Placement
| Component | Path |
|---|---|
| ApiVersion | src/Domain/Shared/Api/ |
| VersionResolverInterface | src/Domain/Shared/Api/ |
| Resolvers | src/Presentation/Middleware/ |
| Middleware | src/Presentation/Middleware/ |
| Unit Tests | tests/Unit/ |
Naming Conventions
| Component | Pattern | Example |
|---|---|---|
| Version VO | ApiVersion |
ApiVersion |
| Resolver Interface | VersionResolverInterface |
VersionResolverInterface |
| Resolver | {Strategy}VersionResolver |
UriPrefixVersionResolver |
| Composite | CompositeVersionResolver |
CompositeVersionResolver |
| Middleware | VersionMiddleware |
VersionMiddleware |
| Deprecation | DeprecationHeaderMiddleware |
DeprecationHeaderMiddleware |
| Test | {ClassName}Test |
ApiVersionTest |
Quick Template Reference
ApiVersion
final readonly class ApiVersion
{
public function __construct(
public int $major,
public int $minor = 0
) {
if ($this->major < 1) {
throw new \InvalidArgumentException('Major version must be at least 1');
}
}
public static function fromString(string $version): self;
public function toString(): string;
public function equals(self $other): bool;
public function greaterThan(self $other): bool;
}
VersionResolverInterface
interface VersionResolverInterface
{
public function resolve(ServerRequestInterface $request): ?ApiVersion;
}
Usage Example
// Create composite resolver
$resolver = new CompositeVersionResolver([
new UriPrefixVersionResolver(),
new AcceptHeaderVersionResolver(),
new QueryParamVersionResolver(),
]);
// Middleware adds version to request attributes
$middleware = new VersionMiddleware($resolver, defaultVersion: new ApiVersion(1));
// In action/controller
$version = $request->getAttribute('api_version');
if ($version->greaterThan(new ApiVersion(1))) {
return $this->respondV2($data);
}
Strategy Comparison
| Strategy | URL Example | Pros | Cons |
|---|---|---|---|
| URI Prefix | /v1/orders |
Explicit, cacheable | URL changes per version |
| Accept Header | Accept: application/vnd.api.v1+json |
Clean URLs | Complex client setup |
| Query Param | /orders?version=1 |
Simple to test | Not RESTful, caching issues |
Anti-patterns to Avoid
| Anti-pattern | Problem | Solution |
|---|---|---|
| Version in Body | Hard to route | Use URI/header/query |
| Unlimited Versions | Maintenance burden | Deprecation policy |
| No Default Version | Breaks existing clients | Configure default |
| Breaking Without Version | Client disruption | Always version breaking changes |
| No Deprecation Notice | Surprise removal | Deprecation/Sunset headers |
| Copy-Paste Controllers | Duplicated code | Version-aware routing |
References
For complete PHP templates and examples, see:
references/templates.md— ApiVersion, resolvers, middleware, deprecation templatesreferences/examples.md— Framework integration and tests
More from dykyi-roman/awesome-claude-code
psr-overview-knowledge
PHP Standards Recommendations (PSR) overview knowledge base. Provides comprehensive reference for all accepted PSRs including PSR-1,3,4,6,7,11,12,13,14,15,16,17,18,20. Use for PSR selection decisions and compliance audits.
22detect-code-smells
Detects code smells in PHP codebases. Identifies God Class, Feature Envy, Data Clumps, Long Parameter List, Long Method, Primitive Obsession, Message Chains, Inappropriate Intimacy. Generates actionable reports with refactoring recommendations.
15clean-arch-knowledge
Clean Architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Clean Architecture and Hexagonal Architecture audits.
15ddd-knowledge
DDD architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Domain-Driven Design audits.
14testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
12bug-root-cause-finder
Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.
12