Legacy PHP

PHP end-of-life dates and the upgrade path from 5.6 to 8.5

Support dates for every PHP branch from 5.6 onwards, with what breaks at each step and where it tends to hurt a business application. All dates and changes are checked against php.net as of 30 October 2026.

By itmarkerz Technologies. Updated 30 October 2026.

How to read this page

Start with the branch your server runs. The first table tells you when it stopped getting fixes. The second table starts at that branch and lists every set of changes between you and your target, in order. Each row links to the migration guide on php.net, which is the complete list. We picked the items that most often matter in ordering, billing and portal systems, the kind of software we are usually asked to move.

To find out what you are running, check the version on the server itself, not on a developer’s laptop.

php -v
php -m          # loaded extensions, including mysql or mcrypt
composer why-not php 8.5   # which packages block a target version

End-of-life dates for branches that have ended

These are the dates php.net lists on its unsupported branches page. After this date a branch gets no releases at all, security or otherwise.

PHP branches past end of life, with dates from php.net
PHP branchEnd of life
5.631 December 2018
7.010 January 2019
7.11 December 2019
7.230 November 2020
7.36 December 2021
7.428 November 2022
8.026 November 2023
8.131 December 2025

Support dates for current branches

Each branch gets two years of active support and two more of security fixes, four years in total, under the php.net support policy. Today only 8.4 and 8.5 still get routine bug fixes, and 8.4 loses them at the end of this year.

Supported PHP branches with release, active support and security support dates from php.net
PHP branchReleasedActive support untilSecurity fixes until
8.28 December 202231 December 202431 December 2026
8.323 November 202331 December 202531 December 2027
8.421 November 202431 December 202631 December 2028
8.520 November 202531 December 202731 December 2029

If you are choosing a target now, 8.5 gives the longest runway. Check that your framework and packages support it first. WooCommerce, for example, says it is tested up to PHP 8.4, so a store may sensibly stop one version short.

The upgrade matrix: what breaks at each step

Read downwards from your version. The date is when the branch you are leaving reached, or will reach, the end of its security support. Items marked deprecated still run on that version.

PHP upgrade steps from 5.6 to 8.5, with what changes and how it appears in a business application
StepLeaving branch endsChanges that matter mostHow it shows upFull list
5.6 to 7.031 December 2018
  • The mysql, ereg, mssql and sybase_ct extensions are gone
  • Many fatal errors become Error exceptions
  • foreach no longer moves the array pointer; list() assigns in a different order
  • ASP and script tags removed; invalid octal literals are parse errors
Every mysql_query() call fails. This is usually the largest single job in the whole path, because it touches every database call.php.net
7.0 to 7.110 January 2019
  • Too few arguments to a user function throws ArgumentCountError
  • $str[] on a string is fatal; assigning by index to an empty string pads it
  • rand() and shuffle() output changes; ext/mcrypt deprecated
  • DateTime includes microseconds
Loose function calls that once only warned now stop the request. Tests comparing two DateTime objects start to fail.php.net
7.1 to 7.21 December 2019
  • count() warns on anything not countable, including null
  • object becomes a reserved name; get_class(null) warns
  • number_format() no longer returns -0
  • mcrypt leaves core for PECL
Pages fill the log with count() warnings, which become errors at 8.0. Anything encrypted with mcrypt needs a plan before this step, including stored data.php.net
7.2 to 7.330 November 2020
  • continue inside switch warns
  • Heredoc closing labels can end the string early
  • If an autoloader throws, later autoloaders no longer run
  • Prepared statements return fractional seconds for DATETIME columns
Usually a quiet step. Old autoload chains and date comparisons against database values are where it bites.php.net
7.3 to 7.46 December 2021
  • Array access on null, bool or int raises a notice
  • fn is reserved; fread() and fwrite() return false on failure
  • Deprecated: unparenthesised nested ternaries, curly-brace offsets, reversed implode(), array_key_exists() on objects
Deprecation noise is the useful output here. It is a preview of what 8.0 will break, so this is a good place to pause and clean up.php.net
7.4 to 8.028 November 2022
  • 0 == "foo" is now false; 42 == "42foo" is now false
  • Same-name methods no longer act as constructors
  • create_function(), each() and the magic-quotes functions removed
  • count() on a non-countable throws TypeError; undefined variables and keys become warnings
  • match is reserved; #[ is no longer a comment
The comparison change is the dangerous one, because nothing errors: a discount rule or status check simply takes a different branch. Old PHP 4 style classes silently lose their constructors.php.net
8.0 to 8.126 November 2023
  • Passing null to internal function parameters deprecated
  • Tentative return types on internal classes need #[\ReturnTypeWillChange] or a real type
  • MySQLi throws exceptions by default; PDO returns native ints and floats for MySQL
  • htmlspecialchars() now escapes single quotes by default
Code wrapping every query in an if-false check stops catching errors. Strict comparisons against numeric strings from the database start to fail.php.net
8.1 to 8.231 December 2025
  • Dynamic properties deprecated
  • ${var} interpolation, utf8_encode() and utf8_decode() deprecated
  • strtolower(), ucfirst() and similar become ASCII-only, ignoring locale
  • str_split("") returns an empty array
Old model classes that set undeclared properties log on every request. Case conversion of accented customer names can change, which matters for matching and sorting.php.net
8.2 to 8.331 December 2026
  • After $a[-5] on an empty array, the next key is -4, not 0
  • The Date extension throws DateError and DateException subclasses
  • range() is stricter; number_format() honours negative decimals
  • Traits with static properties get separate storage per class
A small step for most systems. Date handling that relied on warnings or caught a generic exception needs a look.php.net
8.3 to 8.431 December 2027
  • Implicitly nullable parameters (Foo $a = null) deprecated
  • IMAP, OCI8, PDO_OCI and PSpell move to PECL
  • round() throws ValueError for an invalid mode
  • The MySQL wait-timeout error code changes from 2006 to 4031 on MySQL 8.0.24 and later
Implicit nullables are everywhere in older code, so expect many one-line changes. A system reading mail through IMAP needs the PECL extension or a replacement.php.net
8.4 to 8.531 December 2028
  • Deprecated: the backtick operator, (integer) and (boolean) casts, a semicolon after case, null as an array offset
  • Destructuring a non-array value warns
  • Casting an unrepresentable float to int warns
  • curl_close(), imagedestroy() and mysqli_execute() deprecated; several PDO fetch rules change
Mostly housekeeping for code already clean on 8.4. Code using PDO::FETCH_CLASS constructor arguments or FETCH_PROPS_LATE needs testing.php.net

The four steps that take the most time

5.6 to 7.0: the database layer

The removal of the mysql extension is simple to describe and slow to do. Every query has to move to mysqli or PDO, and if you are touching them anyway it is the moment to switch to prepared statements. Old code often builds SQL by joining strings, so this step is also a security improvement. Budget for reading every query, not for a search and replace.

7.1 to 7.2: mcrypt

PHP deprecated mcrypt in 7.1 and moved it to PECL in 7.2, recommending OpenSSL or Sodium. The code change is small. The real work is any data already encrypted with it: card tokens, stored passwords or personal details have to be decrypted and re-encrypted, and each cipher and padding choice has to be matched exactly. Find this early, because it can’t be fixed by a tool.

7.4 to 8.0: comparisons that change without an error

Most breaks announce themselves. The change to string and number comparison doesn’t. Where old code compares a number with text loosely, the result can flip while the page still loads. This is why tests or a side-by-side run matter more at this step than at any other. On systems with no tests, we write them around the money and permission logic before moving.

8.0 to 8.2: the noise

The null-parameter deprecation in 8.1 and the dynamic-property deprecation in 8.2 don’t stop anything, but in older code they can produce a large volume of log entries. Turn on logging, count them by location, and fix them in batches. Silencing them hides the warning you will need when a later version removes the behaviour.

Stepping through or jumping straight there

Installing each version in turn is rarely worth it on a large jump. A practical sequence for an in-place upgrade is this:

  1. Fix the database layer and any mcrypt use while still on the old version, if the code allows it.
  2. Move to the latest 7.x you can, and clear what its deprecation notices tell you.
  3. Add tests or a parallel run around the logic that handles money, stock and permissions.
  4. Move to the target version, using static analysis and automated refactoring tools for the repetitive changes.
  5. Run old and new side by side on real workflows before you cut over.

On a system with a framework that is itself out of support, moving PHP alone may not be possible, because the framework won’t run on the new version. Then the choice becomes a framework upgrade or a re-platform, which we cover in rewrite or upgrade. For the full route from PHP 5.6, see what breaks going from 5.6 to 8.

If the target is Laravel

Laravel sets its own PHP floor, so the framework version can decide your target. Support dates below come from our Laravel versions page.

Laravel versions, supported PHP versions and support end dates
LaravelPHPBug fixes untilSecurity fixes until
138.3–8.5Q3 2027March 17, 2028
128.2–8.5August 13, 2026February 24, 2027

If your system is already on Laravel and only the runtime is behind, read PHP 8.1 end of life and Laravel instead. This matrix is aimed at custom PHP and older frameworks.

What we have done on this path

We moved a cabinet manufacturer’s ordering, dealer-portal and inventory system from PHP 5.6 and MySQL 5.0 to Laravel 13 on PHP 8.5 and MySQL 8, which is the full length of this table. It took about eight months. We also re-platformed a loyalty-card system we had first built on PHP 5.6 onto Laravel in two months. Separately, we moved a live Belgian WooCommerce store from PHP 7.4 to the current release during a maintenance engagement. Most of our work is delivered under NDA, so many projects cannot be named.

If you want this done for you, our legacy PHP modernisation service starts with an assessment of your code. For wider PHP work, see PHP development.

Systems we have moved off old PHP

Questions

Which PHP versions are still supported in October 2026?

8.2, 8.3, 8.4, 8.5, according to php.net. PHP 8.2 gets security fixes until 31 December 2026, so it has about two months left, and PHP 8.1 reached end of life on 31 December 2025.

Do I have to install every version on the way from 5.6 to 8.5?

No. You read the changes for every step, but you don't have to deploy each one. Many teams pause only at a version that helps: 7.4 for its deprecation warnings, then the final target. If the system is being rebuilt on a framework, you skip the intermediate runtimes altogether.

Is a deprecation the same as a break?

No. Deprecated code still runs and raises a notice. It tells you what a later version may remove. The table lists both because deprecations are the cheapest warning you will get, but only a removal or a behaviour change will stop or alter your application on that version.

Can I run an unsupported PHP version safely behind a firewall?

A firewall reduces who can reach the application, but it doesn't patch anything. php.net publishes no further fixes for an ended branch, so a flaw found later stays open. Hosting, payment and insurance requirements may also matter, and those are questions for your own providers.

More on legacy PHP

Not sure how far behind you are?

Tell us your PHP version and what the system does. You don't need to have read the table.

We reply within one business day (IST).