Cross-Version Compatibility Testing
debt(d5/e3/b3/t6)
Closest to 'specialist tool catches' (d5), PHPCompatibility PHPCS sniffs and CI matrix testing catch version-incompatible API usage, but require explicit setup — silent without them.
Closest to 'simple parameterised fix' (e3), quick_fix involves adding composer.json constraint, PHPCS rule, and CI matrix config — multiple small config changes but no code refactor.
Closest to 'localised tax' (b3), the CI matrix and sniff config impose ongoing maintenance overhead (adding new PHP versions, dropping old ones) but stays contained to CI/tooling layer.
Between 'notable trap' (t5) and 'serious trap' (t7), landing at t6 — the misconception that composer.json's php constraint actually verifies compatibility (it only documents intent) is a common and misleading gotcha.
TL;DR
Explanation
Strategies: (1) GitHub Actions matrix: [php: ['8.1','8.2','8.3']] runs tests against each version. (2) PHPStan with phpCompatibilityFixer to detect usage of features not available in minimum PHP version. (3) composer check-platform-reqs validates extension requirements. (4) phpenv or phpbrew to switch PHP versions locally. (5) Docker: test against official php:8.x-cli images. (6) PHPCompatibility (PHPCS sniff): checks code against target PHP version. Key: declare minimum PHP version in composer.json require->php field and enforce with tooling.
Common Misconception
Why It Matters
Common Mistakes
- Only testing against one PHP version in CI.
- Not specifying minimum PHP version in composer.json.
- Not using PHPCompatibility PHPCS sniffs to catch API usage differences.
Code Examples
# composer.json — no PHP version constraint:
{
"require": {
"php": "*"
}
}
# composer.json:
{
"require": {
"php": ">=8.1"
}
}
# GitHub Actions:
matrix:
php: ['8.1', '8.2', '8.3']
# phpcs.xml:
<rule ref="PHPCompatibility"/>
<config name="testVersion" value="8.1-"/>