From playbooks-virtuoso
Guides Symfony framework version upgrades using a deprecation-first approach: fix all deprecations on the current version before upgrading to the next major. Covers changelog workflow, incremental minor upgrades, recipe updates, bundle compatibility, and PHPUnit Bridge deprecation tracking.
How this skill is triggered — by the user, by Claude, or both
Slash command
/playbooks-virtuoso:symfony-upgradeThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
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.
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 |
npx claudepluginhub krzysztofsurdy/code-virtuoso --plugin agents-virtuosoGuides Symfony project workflows, architecture refinements, and safe change execution with checkpoints and validation.
Step-by-step PHP version upgrade playbook covering 8.0 through 8.4+ with automated tooling. Guides users through auditing, running Rector, fixing deprecations, and testing.
Provides Symfony framework reference with architecture patterns, DDD integration, clean architecture checklists, common violations, and antipatterns for auditing PHP projects.