Legacy PHP
PHP 5.6 to PHP 8: what breaks, and four ways off
PHP 5.6 stopped getting fixes on 31 December 2018. If your system still runs on it, here is what fails when it meets PHP 8, in the order you will meet it, and the four realistic ways off.
By itmarkerz Technologies. Updated 30 October 2026.
What fails, in the order you will hit it
1. The application doesn’t start
PHP 7.0 removed the mysql, ereg, mssql and sybase_ct extensions, so the first page that touches the database dies. Search your code to see how much this covers.
grep -rnE "mysql_[a-z_]+\(|ereg(i)?(_replace)?\(|split\(|mcrypt_" --include="*.php" .PHP 8 itself also rejects some old forms outright: create_function() and each() have gone, and a method named after its class is no longer a constructor. That last one matters in old PHP 4 style classes, because the object is simply created without the setup you expected.
2. Pages start, then stop part way through
Many fatal errors became exceptions in PHP 7, so custom error handlers may no longer fire. Calling a function with too few arguments throws from 7.1. Calling count() on something that can’t be counted warns from 7.2 and throws a TypeError from 8.0. Older code tends to do this on database results that came back empty, so it fails only when there is no data, which is the case nobody tested.
3. Everything appears to work, but some results are different
This is the expensive group, because nothing tells you. The main ones:
- Loose comparison. In PHP 8,
0 == "foo"is false where it used to be true. Status checks and rule tables built on loose comparison can take a different branch. - Random numbers. From 7.1,
rand(),shuffle()andarray_rand()give different output for the same seed. That matters if you stored or relied on a seeded sequence. - Array iteration. foreach no longer moves the internal array pointer, and list() assigns in a different order, so code that depended on either behaves differently.
- Database types. From 8.1, PDO returns native integers and floats for MySQL, so a strict comparison against a string starts to fail.
- Case conversion. From 8.2, strtolower() and its relatives are ASCII-only, which changes results for accented names if your code relied on a locale.
4. Data you can’t read any more
Check for mcrypt, which left core in 7.2. Anything stored with it has to be decrypted and re-encrypted, and that is best planned while the old system can still read it. Also check character encoding: old systems on MySQL 5 are often latin1 at the database level with UTF-8 text inside. Our MySQL 5 to 8 checklist covers this.
For every step in between, see the full PHP upgrade matrix.
Four ways off
| Route | What it means | Fits when | Main risk |
|---|---|---|---|
| In-place upgrade | Same code, new PHP. Fix what breaks. | Small system, tidy code, current design is still fine. | Silent behaviour changes, if there are no tests. |
| Staged upgrade | Move through a midpoint such as 7.4, releasing as you go. | Larger system that can’t freeze, with a team that can keep shipping. | It runs long, and the midpoint becomes the new resting place. |
| Re-platform | Rebuild the application on a framework, keeping the data and every business rule. | No framework or a dead one, but the system’s logic is correct and well used. | Rules nobody wrote down get lost. Needs a side-by-side check. |
| Rebuild | Design the system again, including changes to how it works. | The workflows themselves are wrong, or the business has outgrown them. | Largest scope, and the old system keeps needing care meanwhile. |
Real timelines from our own projects
Published durations for this work are rare, so here are ours. Both are re-platforms, and they sit at very different ends of the range.
- Loyalty-card system, two months. We had built the original on PHP 5.6 ourselves, so we already knew the code. We rebuilt it on Laravel, migrated the data, and kept every card, balance and rule.
- Cabinet manufacturer, about eight months. Ordering, quoting, dealer portal and inventory moved from PHP 5.6 and MySQL 5.0 to Laravel 13, PHP 8.5, MySQL 8 and a new Next.js front end. We audited the code and schema first, validated data at every step of the migration, and checked each workflow against the old system running in parallel.
The gap between them isn’t only size. We already knew the loyalty system’s code, and the cabinet project’s scope also took in a database move and a new front end. Don’t read either as a benchmark. Our rewrite or upgrade comparison looks at what drove the difference, and the cost guide has our published prices.
Choosing: three questions
- Are the business rules correct? If yes, keep them, which rules out a redesign. If people work around the system every day, an upgrade only preserves the problem.
- Can you tell when something has broken? Without tests, a side-by-side run or people who can check results, an in-place upgrade is riskier than it looks.
- Can you hire for what you end up with? The cabinet manufacturer’s system was impossible to hire for. Moving to a supported runtime without moving off an unusual codebase may not solve that.
If you want someone else to run this, see our legacy PHP modernisation service. If your system is already Laravel, however old, Laravel rescue is likely a better starting point.
The two projects above
Cabinet manufacturer's ordering, dealer-portal and inventory system moved from PHP 5.6 and MySQL 5.0 to Laravel 13 on PHP 8.5 and MySQL 8, with a new Next.js front end. Eight months, workflows preserved, now live.
- Sector
- Manufacturing
- Region
- Canada and US
- Stack
- Laravel 13, PHP 8.5, MySQL 8, Next.js
- Engagement
- Upgrade, about eight months, live
Loyalty-card management system we first built on PHP 5.6, re-platformed onto Laravel with all cards, balances and rules preserved. Two months, live since mid-2026, Indian client.
- Sector
- Retail & loyalty
- Region
- India
- Year
- 2026
- Stack
- Laravel
- Engagement
- Upgrade of our own earlier build, two months
Questions
How long does moving from PHP 5.6 to PHP 8 take?
It depends on size, tests and how much the system must keep doing while it moves. Our two projects off PHP 5.6 took two months and about eight months, and both were re-platforms rather than in-place upgrades. We can't give you a meaningful number for your system without reading the code.
Can a tool do the migration for me?
Tools such as Rector and static analysers handle repetitive syntax changes well. They can't tell you whether a discount still calculates correctly after the comparison rules changed, or decide what happens to data encrypted with mcrypt. Use them for the routine part and spend the time you save on checking behaviour.
Should I go to PHP 8.5 or an earlier 8.x?
Aim for the latest version your framework and packages support. PHP 8.5 gets security fixes until 31 December 2029, the longest window available today. PHP 8.2 ends on 31 December 2026, so there is little reason to target it now.
More on legacy PHP
- PHP end-of-life dates and the upgrade path from 5.6 to 8.5Every branch date from php.net, and what breaks at each step.
- MySQL 5 to 8 migration checklistThe supported path, the checks to run, and what to compare afterwards.
- Rewrite or upgrade a legacy PHP system?Three real projects, three different answers.
- What it costs to modernise a legacy PHP systemOur published price ladder for this work, and what moves a quote.
Tell us what your PHP 5.6 system does
We will read the code and tell you which of the four routes we would take, and why.
We reply within one business day (IST).