Why this matters
Symfony releases a new minor version every six months and a new major every two years. Standard versions get bug fixes for eight months, and long-term support (LTS) versions get three years of bug fixes plus a year of security fixes. Applications move forward to keep receiving those fixes, and they can only do so when every bundle and package they use can be installed alongside the new version.
A package that caps its symfony/* constraints at the previous major becomes the reason an application cannot upgrade. Because Symfony applications lock every framework component to one version, a single component left behind is enough to block the install.
What good looks like
- The package's
composer.jsonallows the current Symfony major for every framework component it depends on. - The test suite runs against the current Symfony version in CI.
- New majors are supported soon after release, ideally by testing against the pre-release versions.
How to do it
Widen the constraints
List every symfony/* component you depend on and add the new major to each:
{
"require": {
"php": ">=8.2",
"symfony/console": "^6.4 || ^7.0 || ^8.0",
"symfony/http-kernel": "^6.4 || ^7.0 || ^8.0",
"symfony/yaml": "^6.4 || ^7.0 || ^8.0"
}
}
The components must move together. A symfony/yaml constraint stuck at ^7.0 blocks a Symfony 8 application even if every other component allows 8.
Independently versioned packages such as symfony/polyfill-*, the symfony/*-contracts packages, symfony/flex, and symfony/ux-* have their own release cycles and do not need to match the framework version.
Check your dependencies
Your package can only install with the new Symfony if everything it depends on can too. Run a real resolution in a fresh skeleton:
composer create-project symfony/skeleton:"8.0.*" probe
cd probe
composer require your-vendor/your-bundle
If Composer refuses, the message names the conflicting dependency. Update it or wait for it to add support.
Test against the new version
Use Symfony Flex and the extra.symfony.require setting to pin the framework version per CI job:
strategy:
matrix:
symfony: ['6.4.*', '7.4.*', '8.0.*']
steps:
- run: composer global config --no-plugins allow-plugins.symfony/flex true
- run: composer global require symfony/flex
- run: composer config extra.symfony.require "${{ matrix.symfony }}"
- run: composer update --prefer-dist --no-progress
- run: vendor/bin/phpunit
Release
Tag a new version. The constraint on your default branch reaches nobody until it is released.
Things to watch for
- Deprecations. Symfony announces removals one major ahead through deprecation notices. Running your tests with
SYMFONY_DEPRECATIONS_HELPERon the last minor of the current major shows exactly what the next major will break. conflictentries. Aconflictagainst a newer Symfony version blocks installation even whenrequirelooks right. Review and remove stale ones.- Constraints hidden in dependencies. A bundle you depend on may be the one holding you back. The resolution test names it.
- Dropping the LTS too early. Many applications sit on the LTS release for years. Keep the current LTS in your matrix and constraints alongside the newest major.