symfony-upgrade
Symfony Framework Upgrade
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.
Core Principles
| 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 |
Critical First Step: Read the Changelog
Before touching any code or running any command, you MUST obtain the actual changelog for the target version:
- Search the web for
Symfony UPGRADE-X.Y.md(e.g.,Symfony UPGRADE-7.0.md github) - Or ask the user to provide the changelog / release notes
- Read the UPGRADE file in the Symfony repository:
https://github.com/symfony/symfony/blob/X.Y/UPGRADE-X.Y.md - Check the Symfony blog for the release announcement with highlighted changes
This 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.
Symfony Release Model
| 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).
Minor Version Upgrade (e.g., 7.3 -> 7.4)
Step 1: Read the Changelog
Search the web for UPGRADE-7.4.md in the Symfony repository. Identify new deprecations and any changes that affect your code.
Step 2: Update composer.json
With Symfony Flex (recommended):
{
"extra": {
"symfony": {
"require": "7.4.*"
}
}
}
Without Flex, update each symfony/* constraint manually.
Step 3: Run Composer Update
composer update "symfony/*"
If dependency conflicts arise:
composer update "symfony/*" --with-all-dependencies
Step 4: Update Recipes
composer recipes:update
Step 5: Run Tests
vendor/bin/phpunit
Major Version Upgrade (e.g., 6.4 -> 7.0)
Phase 1: Read the Changelog
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.
Phase 2: Eliminate All Deprecations
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
Phase 3: Bump Symfony Version
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.
Phase 4: Update Recipes
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.
Phase 5: Test Thoroughly
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.
SYMFONY_DEPRECATIONS_HELPER Options
| 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) |
Handling Third-Party Bundles
Bundles are the most common upgrade blocker. Follow this order:
- Check compatibility -- look at each bundle's
composer.jsonfor Symfony version constraints - Update bundles first --
composer updatebefore bumping Symfony version - Check for forks -- if a bundle is abandoned, look for maintained forks on Packagist
- Wrap risky dependencies -- use adapter pattern to isolate bundles that may not keep up
For 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"
}
}
Quick Reference: Major Upgrade Checklist
- Search the web for
UPGRADE-X.0.mdand read it completely - Upgrade to the last minor of current major (e.g., 6.4)
- Update all third-party bundles to latest versions
- Configure
SYMFONY_DEPRECATIONS_HELPERwithmax[direct]=0 - Run test suite and fix all direct deprecations
- Run Rector with Symfony deprecation rules
- Verify zero direct deprecations in test output
- Update
extra.symfony.requireto new major version - Run
composer update "symfony/*" --with-all-dependencies - Clear cache:
rm -rf var/cache/* - Run
composer recipes:updateuntil all recipes are current - Run full test suite
- Run static analysis
- Deploy to staging and verify
- Deploy to production and monitor logs
Reference Files
| Reference | Contents |
|---|---|
| Upgrade Workflow | Detailed deprecation handling workflow, recipes:update deep dive, CI pipeline integration, and version-specific migration notes |
Integration with Other Skills
| 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 |
More from krzysztofsurdy/code-virtuoso
symfony-components
Comprehensive reference for all 38 Symfony framework components with PHP 8.3+ and Symfony 7.x patterns. Use when the user asks to implement, configure, or troubleshoot any Symfony component including HttpFoundation, HttpKernel, DependencyInjection, Form, Validator, Cache, Messenger, Console, EventDispatcher, Workflow, Serializer, Security, Routing, Twig, Doctrine integration, or any other Symfony component. Covers APIs, configuration, best practices, and common pitfalls.
80solid
SOLID principles for object-oriented design with multi-language examples (PHP, Java, Python, TypeScript, C++). Use when the user asks to review SOLID compliance, fix a SOLID violation, evaluate class design, reduce coupling, improve extensibility, or apply Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, or Dependency Inversion principles. Covers motivation, violation detection, refactoring fixes, and real-world trade-offs for each principle.
46agentic-rules-writer
Interactive tool to generate tailored rules and instruction files for any AI coding agent. Use when the user asks to set up agent rules, configure Claude Code instructions, create Cursor rules, write Windsurf rules, generate Copilot instructions, or establish consistent AI coding standards for a team. Supports 13+ agents (Claude Code, Cursor, Windsurf, Copilot, Gemini, Codex, Cline, OpenCode, Continue, Trae, Roo Code, Amp) with global, team-shared, and dev-specific scopes. Defers to the `using-ecosystem` meta-skill for ecosystem discovery (skills, agents, recommendations) and runs an interactive questionnaire for workflow preferences.
46refactoring
Comprehensive skill for 89 refactoring techniques and 22 code smells with practical examples. Use when the user asks to refactor code, detect code smells, improve code quality, reduce complexity, or clean up technical debt. Covers composing methods, moving features between objects, organizing data, simplifying conditionals and method calls, dealing with generalization, and detecting smells across bloaters, OO abusers, change preventers, dispensables, and couplers with before/after comparisons and step-by-step mechanics.
41clean-architecture
Clean Architecture, Hexagonal Architecture (Ports and Adapters), and Domain-Driven Design fundamentals. Use when the user asks to design system architecture, define layer boundaries, apply DDD tactical patterns (entities, value objects, aggregates, repositories), structure a hexagonal application, enforce dependency rules, or evaluate whether a codebase needs architectural refactoring. Covers bounded contexts, use cases, domain services, and framework-independent design.
40security
Application security principles and OWASP Top 10 for building secure web applications. Use when the user asks to review code for security vulnerabilities, implement authentication or authorization, handle secrets or API keys, configure security headers, prevent injection attacks (SQL, XSS, CSRF), prepare for a security audit, or respond to a vulnerability report. Covers input validation, data protection, secrets management, session handling, and common security antipatterns.
39