From playbooks-virtuoso
Guides Symfony framework upgrades to minor/major/LTS versions via deprecation-first approach: review changelogs, fix deprecations, update recipes/bundles, check compatibility.
npx claudepluginhub krzysztofsurdy/code-virtuoso --plugin playbooks-virtuosoThis skill is limited to using the following tools:
Symfony's upgrade model is built on one core insight: a new major version is identical to the last minor version of the previous branch, minus deprecated code. Fix all deprecations first, then the major upgrade is trivial.
Applies production-grade Symfony architecture and execution workflows with controlled scope, checkpoints, and validation for safe medium/complex changes.
Guides step-by-step PHP upgrades from 8.0 to 8.4+ using Rector for refactoring, PHPCompatibility for audits, and strategies for deprecations, extensions, and testing.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Share bugs, ideas, or general feedback.
Symfony's upgrade model is built on one core insight: a new major version is identical to the last minor version of the previous branch, minus deprecated code. Fix all deprecations first, then the major upgrade is trivial.
| Principle | Meaning |
|---|---|
| Changelog first | Before any upgrade, search the web for the actual UPGRADE-X.Y.md file or ask the user for the changelog -- never rely on static knowledge alone |
| Deprecation-first | Fix every deprecation on the current version before upgrading to the next major -- Symfony 8.0 is 7.4 minus deprecations |
| Incremental minor upgrades | Upgrade 6.2 -> 6.3 -> 6.4, never skip minors -- each surfaces new deprecations |
| Recipes keep config current | Run composer recipes:update after every upgrade to sync configuration files |
| Test deprecation count | Use SYMFONY_DEPRECATIONS_HELPER to fail builds when direct deprecations appear |
| Update bundles first | Third-party bundles are the most common blocker -- update them before bumping Symfony |
Before touching any code or running any command, you MUST obtain the actual changelog for the target version:
Symfony UPGRADE-X.Y.md (e.g., Symfony UPGRADE-7.0.md github)https://github.com/symfony/symfony/blob/X.Y/UPGRADE-X.Y.mdThis is non-negotiable. Each version has unique changes that static skill knowledge cannot fully capture. The changelog tells you exactly what broke, what was deprecated, and what was removed.
| Release Type | Cycle | Support | Example |
|---|---|---|---|
| Patch (X.Y.Z) | Monthly | Bug fixes only | 7.4.1 -> 7.4.2 |
| Minor (X.Y) | Every 6 months (May + November) | May add deprecations, no BC breaks | 7.3 -> 7.4 |
| Major (X.0) | Every 2 years (November, odd years) | Removes deprecated code, may have BC breaks | 7.x -> 8.0 |
| LTS (X.4) | Always the X.4 release | 3 years bug fixes, 4 years security fixes | 6.4 LTS, 7.4 LTS |
Each major branch has exactly 5 minor versions: X.0, X.1, X.2, X.3, X.4 (LTS).
Search the web for UPGRADE-7.4.md in the Symfony repository. Identify new deprecations and any changes that affect your code.
With Symfony Flex (recommended):
{
"extra": {
"symfony": {
"require": "7.4.*"
}
}
}
Without Flex, update each symfony/* constraint manually.
composer update "symfony/*"
If dependency conflicts arise:
composer update "symfony/*" --with-all-dependencies
composer recipes:update
vendor/bin/phpunit
Search the web for UPGRADE-7.0.md in the Symfony repository. This file lists every backward-compatibility break and every removed deprecation. Read it completely before starting.
This is the bulk of the work. Do this while still on the current major version.
A. Detect deprecations via tests:
composer require --dev symfony/phpunit-bridge
Configure strict deprecation handling in phpunit.xml.dist:
<php>
<env name="SYMFONY_DEPRECATIONS_HELPER" value="max[direct]=0"/>
</php>
Run tests and fix every direct deprecation:
vendor/bin/phpunit
B. Detect deprecations in browser:
Visit the app in dev environment, check the Symfony Profiler's deprecation panel in the web debug toolbar.
C. Automate fixes with Rector:
composer require --dev rector/rector rector/rector-symfony
// rector.php
use Rector\Config\RectorConfig;
use Rector\Symfony\Set\SymfonySetList;
return RectorConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withSets([SymfonySetList::SYMFONY_70]);
vendor/bin/rector process --dry-run
vendor/bin/rector process
D. Handle indirect deprecations:
Indirect deprecations come from third-party bundles. Update them to versions that support the target Symfony version:
composer outdated
composer update vendor/bundle-name
With Flex:
{
"extra": {
"symfony": {
"require": "7.0.*"
}
}
}
composer update "symfony/*" --with-all-dependencies
rm -rf var/cache/*
Note: packages like symfony/polyfill-*, symfony/ux-*, and some symfony/*-bundle follow their own versioning -- do not force them to the new major.
composer recipes # list all, see which have updates
composer recipes:update # interactive update, one at a time
The command generates a diff between your installed recipe version and the latest, applies it as a git patch. Resolve conflicts like normal git conflicts. Commit your work before running this.
vendor/bin/phpunit
vendor/bin/phpstan analyse
Deploy to staging before production.
See Upgrade Workflow Reference for detailed deprecation handling, SYMFONY_DEPRECATIONS_HELPER options, and bundle compatibility strategies.
| Configuration | Effect |
|---|---|
max[direct]=0 | Fail on any deprecation caused by your code |
max[indirect]=999 | Tolerate deprecations from vendor code during transition |
max[total]=0 | Fail on any deprecation from any source (strictest) |
disabled=1 | Disable deprecation tracking entirely (not recommended) |
generateBaseline=true&baselineFile=./tests/allowed.json | Snapshot current deprecations to a baseline file |
baselineFile=./tests/allowed.json | Ignore deprecations already in the baseline (ratchet approach) |
Bundles are the most common upgrade blocker. Follow this order:
composer.json for Symfony version constraintscomposer update before bumping Symfony versionFor bundle maintainers, use feature detection instead of version checks:
// Bad -- version-based check
if (Kernel::VERSION_ID <= 60400) { ... }
// Good -- feature-based check
if (!method_exists(OptionsResolver::class, 'setDefined')) { ... }
Support multiple versions with flexible constraints:
{
"require": {
"symfony/framework-bundle": "^6.4|^7.0"
}
}
UPGRADE-X.0.md and read it completelySYMFONY_DEPRECATIONS_HELPER with max[direct]=0extra.symfony.require to new major versioncomposer update "symfony/*" --with-all-dependenciesrm -rf var/cache/*composer recipes:update until all recipes are current| Reference | Contents |
|---|---|
| Upgrade Workflow | Detailed deprecation handling workflow, recipes:update deep dive, CI pipeline integration, and version-specific migration notes |
| Situation | Recommended Skill |
|---|---|
| Upgrading PHP version alongside Symfony | Use the php-upgrade playbook skill |
| Updating Composer dependencies | Use the composer-dependencies playbook skill |
| Working with Symfony components | Use the symfony-components skill in frameworks/symfony/ |
| Modernizing PHP code patterns | Install php-modernization from dirnbauer/webconsulting-skills |