PHP upgrade and modernization for apps that can’t stop
A PHP upgrade gets your application onto a version that still receives security patches, without a rewrite and without freezing feature work. I do it in small, tested steps: static analysis to find what breaks, Rector to fix the mechanical parts, and a CI matrix that proves each step before it ships.
I’ve been writing PHP in production for a long time. I built the PHP framework at Yola as it grew from 10K to 11M users, and I wrote GUMP, an open-source PHP validation library used on thousands of websites.
Why the PHP version matters now
PHP 7.4 reached end of life in November 2022. PHP 8.0 followed in late 2023, and PHP 8.1 lost security support at the end of 2025. If you’re on any of those, you’re running a runtime that won’t get a patch for the next CVE. For later versions, check the official EOL schedule on php.net – the support windows were extended in 2024, so older blog posts are often wrong.
The practical pressure usually shows up somewhere else first: your hosting provider or base Docker image drops the old version, a payment SDK requires 8.x, or a security questionnaire from an enterprise customer asks what runtime you’re on.
How a PHP 8 upgrade actually runs
- Inventory. PHP version per environment, extensions in use, every Composer dependency and whether it supports the target version (composer why-not php 8.4 answers that quickly). Abandoned packages get flagged early – they’re usually the long pole.
- Static analysis baseline. PHPStan at a low level with a baseline file, plus PHPCompatibility rules in PHP_CodeSniffer. This turns “what will break?” into a concrete list instead of a guess.
- CI on both versions. The test suite runs on the current and target PHP versions side by side. If there are few tests, I add characterization tests around the critical paths first: checkout, login, billing, anything with money.
- Rector for the mechanical work. Rector rewrites code with AST transformations: removed functions like each() and create_function(), constructor promotion, typed properties, null-safe calls. I apply one rule set per pull request so each diff stays reviewable.
- Hand-fix the semantic changes. The changes Rector can’t safely automate: PHP 8’s new string-to-number comparison rules, passing null to non-nullable internal function parameters (deprecated in 8.1), dynamic properties (deprecated in 8.2), and stricter type errors from internal functions.
- Roll out gradually. One server or container pool on the new version first, error rates and logs compared against the old pool, then the rest. Rollback is a config change.
Legacy PHP modernization beyond the version bump
A version upgrade is the right moment to fix what made the code hard to upgrade. Not everything – just the things that will bite again next time.
- Composer and autoloading for code that still uses require_once chains and global functions.
- Raising the PHPStan level a step at a time and shrinking the baseline, so new code can’t add new type problems.
- **Replacing mysql_* or hand-built SQL strings** with PDO and prepared statements – a security fix as much as a modernization.
- Pulling business logic out of templates and into classes that can be tested.
- Moving off a dead framework using the strangler fig pattern: route by route onto Symfony components or Laravel, behind the same front controller.
When it’s more than an upgrade
Sometimes the PHP version is a symptom. If the codebase can’t be upgraded because nobody understands it, the problem is broader, and legacy modernization is the better frame. If you’re on Laravel specifically, see Laravel consulting – framework upgrades have their own sequence.
And if your app is small, well tested and on a mainstream framework, you may not need me at all. Run Rector with the right set list, fix what PHPStan reports, and test on staging. That’s honestly most of the job for a clean codebase.
Questions
When did PHP 7.4 reach end of life?
PHP 7.4 reached end of life in November 2022 and receives no security fixes. Some Linux distributions backport patches into their own packaged builds, but if you deploy from official images or a managed host, assume 7.4 is unpatched and plan a PHP 8 upgrade.
Is PHP 8.1 end of life?
Yes. PHP 8.1 lost active support in late 2023 and security support at the end of 2025. Upgrading from 8.1 to a current 8.x release is usually much smaller than the jump from 7.4, mostly deprecations rather than breaking changes.
How long does a PHP 8 upgrade take?
For a tested app on a maintained framework, it can be days. For a large legacy codebase with few tests and abandoned dependencies, it’s weeks of incremental work. The two-week sprint gets you a real inventory and the first upgrades shipped, so the rest can be estimated from evidence.
Can Rector upgrade my PHP code automatically?
Rector handles a large share of the mechanical changes reliably, using version set lists. It can’t judge semantic changes like the new string comparison rules, and it won’t fix abandoned dependencies. Treat it as a fast, reviewable first pass, not the whole upgrade.
Stuck on an unsupported PHP version?
Send me the version you’re on and roughly how big the app is. In a two-week sprint I’ll map what breaks and ship the first upgrades to production.
GMT+2 · Full EU overlap · US East mornings