Why this matters
Every PHP version has a lifecycle: about two years of active support with bug fixes, then a period of security fixes only, then nothing. Applications need to move to newer PHP versions to keep receiving fixes. They can only do that if every package they depend on allows the new version.
A package whose composer.json rules out the current PHP release becomes the reason an application cannot upgrade. Often the code would run fine; the constraint is simply out of date.
What good looks like
The php requirement in composer.json allows the current stable PHP release, and the test suite runs against it in CI so the claim is backed by evidence.
How to do it
Loosen the constraint
Look at the require.php entry in composer.json. A caret constraint allows newer minor versions within the same major:
{
"require": {
"php": "^8.2"
}
}
This allows 8.2, 8.3, 8.4, and so on, but not 9.0. If your constraint names specific versions, such as 8.2.* || 8.3.*, each new PHP release needs a manual edit; a caret constraint does not. Raising the minimum version in a new major release of your package is fine, but the upper bound is what usually blocks users.
Test against the new version
Add the current PHP version to your CI matrix as soon as it is released. Most projects use shivammathur/setup-php on GitHub Actions or the official php images on GitLab CI:
strategy:
matrix:
php: ['8.2', '8.3', '8.4', '8.5']
Run the suite with --prefer-lowest on the oldest version too, so the whole declared range is tested.
Fix what breaks
New PHP versions deprecate and remove things. The migration guide for each release lists them. Static analysis tools such as PHPStan and Psalm, and automated refactoring with Rector, can find most of the changes needed before you even run the tests.
Release
Tag a new version once CI is green. Users install tags, so a widened constraint on the default branch helps nobody until it is released.
Things to watch for
- A missing constraint is a missing promise. Declaring
"php": "^8.2"documents what you actually test. - Blocking the next major early.
^8.2stops at 9.0 by design, since a new major may break compatibility. When PHP 9 arrives, test it and widen the constraint to^8.2 || ^9.0. - A dependency that blocks you. If one of your own dependencies does not support the new PHP yet, your constraint alone will not make the package installable. Update or replace that dependency.
- Platform config hiding problems.
config.platform.phpincomposer.jsontells Composer to pretend a PHP version. Make sure it does not hide a real incompatibility.