Legacy & Modernization
Migrating from PHP 5.6/7.x to PHP 8.3: A Practical Roadmap
Running PHP 5.6 or 7.x in 2026 means unsupported runtimes, security exposure, and a tax on every new feature. Here's the migration roadmap I use with clients — incremental, tested, and aligned with the business calendar.
Why upgrade now
- PHP 7.4 reached end-of-life in November 2022 — no security patches.
- PHP 8.x delivers 15–30% performance gains out of the box (JIT, opcache improvements).
- Modern PHP (typed properties, enums, readonly, first-class callable syntax) reduces bug surface dramatically.
- Most modern libraries no longer support PHP 7.
The 6-phase roadmap
Phase 1 — Audit (1–2 weeks)
- Inventory: PHP version, framework version, all composer dependencies and their PHP requirements.
- Run PHPStan at level 0–3 to baseline current type coverage.
- Identify deprecated APIs with `phan` or `vimeo/psalm`.
- List third-party libraries with no PHP 8 support — these need replacements or forks.
Phase 2 — Stabilize tests (2–4 weeks)
You can't refactor what you can't verify. Before touching PHP versions, get test coverage on the critical paths (auth, payments, data writes). You don't need 90% coverage — you need confidence on the routes that pay the bills.
Phase 3 — Automated rewrites with Rector (1–3 weeks)
Rector applies the bulk of syntax-level migrations automatically. Run it incrementally with focused rule sets:
composer require rector/rector --dev
./vendor/bin/rector process src --set=php80
./vendor/bin/rector process src --set=php81
./vendor/bin/rector process src --set=php82Phase 4 — Manual fixes & dependency upgrades (2–6 weeks)
- Resolve dependency conflicts in composer.json.
- Replace abandoned packages with modern alternatives.
- Address Rector edge cases — magic methods, dynamic properties (now deprecated), reference returns.
- Update framework (Laravel 5 → 11 is a separate roadmap of its own).
Phase 5 — Staging & soak (1–2 weeks)
Deploy to a production-mirror environment. Run the full test suite, plus synthetic load. Watch error rates, response times, memory usage. Pay attention to type coercion changes — PHP 8 is stricter, and silent bugs in PHP 7 become loud exceptions.
Phase 6 — Production rollout
If you're on Kubernetes or have multiple workers, do a canary: 5% → 25% → 100%. If you're on a single server, schedule a maintenance window — but most modern hosts let you swap PHP versions per host with FPM pools.
Realistic timeline
- Small app (<50k LOC, modern framework): 2–4 weeks.
- Medium app (50–200k LOC, Laravel 5–8): 6–12 weeks.
- Large legacy (200k+ LOC, custom framework or old Symfony): 3–6 months.
Risks people underestimate
- Dynamic properties: PHP 8.2+ deprecates them. Lots of legacy code breaks subtly.
- Stricter type juggling: comparisons like `0 == 'foo'` flip from true to false.
- Date/time defaults change behavior for partial date strings.
- Removed extensions (mcrypt) — if you're still using them for old encrypted data, plan re-encryption.
What you get on the other side
Beyond performance and security: smaller bug count thanks to types, easier hiring (modern engineers refuse legacy projects), and access to the modern PHP ecosystem (Laravel 11+, Symfony 7+, modern testing tools).
Need a hand?
Hiring or modernizing PHP? Let's talk.
16+ years building, scaling, and rescuing PHP applications. Direct contact, no marketplace, US time zones from LATAM.
Related reading
How to Rescue a Legacy PHP Project Without a Full Rewrite
A pragmatic playbook for modernizing a legacy PHP codebase incrementally using the strangler pattern — without freezing the business.
Laravel vs Raw PHP vs Symfony: Choosing the Right Stack in 2026
An honest comparison of Laravel, Symfony, and raw PHP in 2026 — when each one is the right call, and when it isn't.