How to Upgrade an Old PHP Site Safely After PHP2Shell

By: Irina Shvaya | October 23, 2026
PHP2Shell, October 2026: two critical flaws in PHP itself (CVE-2026-109618 and CVE-2026-109619) were fixed on 21 October 2026 in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Any site running on PHP needs the server updated. See our PHP2Shell Resource Center.

As of 23 October 2026, the only official PHP2Shell fixes are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. If your site runs PHP 8.1 or older, the lasting fix is to move it to a supported branch, and for most sites that means PHP 8.3 or 8.4. Vendor-patched builds of old PHP can keep you online for now, but they are a bridge, not a destination.

A safe upgrade follows the same order every time: patch or isolate today, take an inventory, back up, copy the site to staging, update the CMS and extensions, switch PHP on staging, fix what breaks, then switch the live site with a tested way back. The risky part is never the PHP switch itself. It is old plugins, themes and custom code that relied on behavior PHP has since changed.

This guide is the practical plan. It lists the changes that break sites at each version jump, links PHP's official migration guides, and explains when a rebuild costs less than an upgrade.

Key Takeaways

  • Patch or isolate first. An upgrade takes days or weeks; PHP2Shell needs action today.
  • Target PHP 8.3 or 8.4. PHP 8.2 is fixed but reaches end of life on 31 December 2026.
  • Inventory every site, the PHP build that actually serves it, the CMS version, every extension and any custom code before you change anything.
  • Test on a staging copy with full error logging. Scanners such as PHPCompatibility help, but they miss runtime problems, and WP Engine's old checker plugin is unmaintained.
  • The 7.4 to 8.0 jump causes the most breakage. 8.1 to 8.3 is mostly deprecation warnings.
  • Keep a rollback path that lands on a patched build, never an unpatched one. If the CMS is end of life or most extensions are abandoned, price a rebuild.

Step 1: Deal With PHP2Shell Before You Plan the Upgrade

An upgrade project should not leave a vulnerable site online while it runs. Before you start, do one of these:

  • Install a vendor-patched build of your current PHP. Many distributions and control panels patched end-of-life branches: Ubuntu 22.04 for 8.1, RHEL 9 for 8.0, RHEL 8 for 7.4, plus cPanel, Plesk and CloudLinux. Our pages for PHP 8.1, PHP 7.4 and PHP 7.3 and older list what exists for each branch.
  • Apply PHP's interim mitigations if no patched build exists, knowing PHP says they "do not make an installation safe." See our guide to PHP2Shell interim mitigations.
  • Isolate the site if you can do neither. CISA says systems on "PHP 8.1 or earlier unsupported versions" should be taken offline "until they can be patched or updated."

If the site was exposed while unpatched, check it for signs of compromise before you copy it anywhere. Upgrading a compromised site carries the compromise forward.

Step 2: Take an Inventory

Write down, for every site and server:

  1. The PHP build that serves the website. Not the command-line version, which watchTowr warns "can be a different version from the one PHP-FPM or Apache runs." Our guide on how to check your PHP version shows how.
  2. Where PHP comes from: your Linux distribution, a control panel (cPanel, Plesk, DirectAdmin), a third-party repository, a container image or your host.
  3. The CMS or framework and its exact version: WordPress, Drupal, Joomla, Magento, Laravel or custom code.
  4. Every plugin, module, extension and theme, with its version and whether it is still maintained.
  5. Custom code: child themes, custom plugins, integrations, payment or booking code.
  6. PHP extensions the site uses. Some have been removed from PHP over time. PHP 8.4 moved IMAP, OCI8, PDO_OCI and PSpell out of the core distribution, which breaks code that reads mail with imap_ functions.
  7. Anything else that runs PHP: cron jobs, command-line scripts, webmail and admin tools on the same server.

The inventory tells you how big the job is. A current WordPress site with a dozen maintained plugins is a short project. A custom application with code from 2015 is not.

Step 3: Choose Your Target Version

Pick a branch with years of support left and that your CMS supports. The dates below are from PHP's supported versions page as of 23 October 2026.

BranchPHP2Shell fixSecurity support untilGood target?
8.58.5.1231 Dec 2029Yes, if your CMS and extensions support it
8.48.4.2731 Dec 2028Yes
8.38.3.3631 Dec 2027Yes; the safest choice for older code
8.28.2.3531 Dec 2026Only as a short step

Your CMS sets limits:

  • WordPress recommends "PHP version 8.3 or greater." WordPress 7.0 and 7.1 run on PHP 7.4 to 8.5.
  • Drupal 11 needs PHP 8.3 or newer; only Drupal 11.3 and 11.4 support 8.5. Drupal 10.4 to 10.6 support 8.1 to 8.4.
  • Joomla 6 needs PHP 8.3 and recommends 8.4. Joomla 5 needs 8.1 and recommends 8.3.
  • Magento 2.4.8 supports PHP 8.4 and 8.3; 2.4.9 lists 8.5.
  • Laravel 13 "requires a minimum PHP version of 8.3."

For most older sites, PHP 8.3 is the sensible landing point: fixed, supported until the end of 2027 and accepted by current WordPress, Drupal and Joomla releases.

Step 4: Back Up and Build a Staging Copy

Never test a PHP upgrade on the live site. You need two things first:

  1. A full, tested backup of files and database, stored off the server. Test that you can restore it. Our guide to website backup and recovery explains what a usable backup looks like.
  2. A staging copy on a server, or a separate site in the same hosting account, where you can choose the PHP version. Some hosts include staging tools. Our guide to WordPress staging sites covers setup and the mistakes to avoid, such as staging copies that send real emails or charge real cards.

Make the staging server's PHP the target version, with the patched build (8.3.36 or later, for example). Match the live server in everything else, including PHP extensions, so the test means something.

Step 5: Update the CMS and Extensions on the Old PHP First

On staging, still on your old PHP, update the CMS core and every plugin, module and theme to the newest versions that support both your current PHP and your target. Most compatibility fixes for new PHP versions arrive in extension updates, so this step removes many problems before you touch PHP.

  • Remove plugins and modules you no longer use. Every one is code that has to work on PHP 8.
  • Flag anything with no update in years. Abandoned extensions are the most common cause of failed PHP upgrades.
  • If the CMS itself is past end of life (Joomla 3, Drupal 7, WordPress branches without security support), the CMS upgrade is the bigger project. See the CMS notes below.

Step 6: Scan and Test for Compatibility

Use two kinds of check. Neither is enough alone.

Static scanning

Static scanners read code without running it and flag functions and syntax that changed. The PHPCompatibility project is a set of rules for the PHP_CodeSniffer tool that "checks for PHP cross-version compatibility." You tell it which versions to test, for example --runtime-set testVersion 8.3-. Its maintainers are clear that "coverage is not yet 100%." It is a developer tool; a non-technical owner should ask their developer to run it.

For WordPress, avoid relying on WP Engine's PHP Compatibility Checker plugin. Its own listing now says it "is no longer actively maintained," it checks compatibility only "up to PHP 8.0," and it "cannot detect runtime compatibility issues." For Drupal, the Upgrade Status module "checks if your system meets the next major version's system requirements" and reviews the site's components before a major Drupal upgrade.

Runtime testing

Then switch the staging site to the target PHP and use it. Turn on full error logging on staging only: error_reporting=E_ALL, log_errors=On and a working error_log, with display_errors off. Restart PHP after the change. Then test:

  • Every page template, form and search.
  • Logins, the admin area and content editing.
  • File and image uploads, imports and exports.
  • Checkout, payments, bookings and any third-party integration.
  • Scheduled tasks and email sending.

Read the error log after each round. Fatal errors must be fixed. Deprecation notices can usually wait, but each one is a problem for the next upgrade.

The Breaking Changes, Jump by Jump

You absorb every change between your current version and your target. These are the ones most likely to affect older sites, from PHP's official migration guides. Follow the links for the full lists.

JumpChanges most likely to break or warn
5.6 to 7.0 (guide)The old mysql extension and the ereg functions removed; many fatal errors became exceptions; indirect variable expressions evaluated left to right; PHP 4-style constructors deprecated
7.0 to 7.47.1: too few arguments to a user function throws an Error. 7.2: count() on non-countable values warns; create_function() and each() deprecated. 7.4: using null or a number as an array gives a notice; curly-brace offsets deprecated
7.4 to 8.0 (guide)Number-to-string comparisons changed (0 == "not-a-number" is now false); create_function() and each() removed; many warnings became Error exceptions; @ no longer silences fatal errors; default error level is E_ALL; curly-brace offsets removed; match reserved; class-named methods no longer constructors
8.0 to 8.1 (guide)No write access to the whole $GLOBALS array; return types required on internal method overrides (deprecation otherwise); readonly and never reserved; FTP, IMAP, LDAP, PgSQL and FileInfo resources became objects
8.1 to 8.2 (guide)Dynamic properties deprecated, the most common new warning in older plugins; utf8_encode() and utf8_decode() deprecated; "${var}" interpolation deprecated; case conversion no longer locale-sensitive
8.2 to 8.3Date errors become DateError and DateException exceptions; ++ on non-numeric strings deprecated; get_class() without arguments deprecated
8.3 to 8.4IMAP, OCI8, PDO_OCI and PSpell moved to PECL; implicitly nullable parameters deprecated; E_STRICT removed; invalid types passed to exit() throw a TypeError

If you are crossing from 7.x into 8.x, budget most of your testing time there. From 8.1 onward, the changes are mainly deprecations that log warnings rather than stop pages.

Step 7: Switch the Live Site, With a Way Back

Once staging runs cleanly on the target PHP, plan the live switch:

  1. Pick a quiet time and tell anyone who edits the site to stop for the window.
  2. Take a fresh backup right before the switch.
  3. Deploy the updated CMS and extensions you tested on staging.
  4. Change the PHP version. On cPanel, the MultiPHP Manager sets the PHP version per domain. On Plesk or another panel, use its PHP version setting for the site, or ask your host. On your own server, install the new branch's packages and point the site at them. Leave the old version installed for now.
  5. Restart PHP. Restart PHP-FPM for the new version, or Apache if you use mod_php, so no old worker keeps serving pages.
  6. Confirm the version that serves the site, then repeat your key tests on the live site and watch the error log for a day.

Your rollback plan is switching the site back to the old PHP, plus restoring the backup if the database changed. One rule matters because of PHP2Shell: only roll back to a patched build. Rolling back to an unpatched 8.1.34 or 7.4.33 to "get the site working" puts you back where you started. If no patched build of your old version exists, your fallback is a maintenance page, not old PHP.

CMS-Specific Notes

WordPress

WordPress shows the PHP version under Tools > Site Health > Info > Server, but a backported fix keeps the old number there, so it cannot prove you are patched. WordPress 7.0 dropped PHP 7.2 and 7.3, so a site on those versions is stuck on WordPress 6.9 until PHP is upgraded. Update WordPress core, plugins and theme before switching PHP, since that is where most PHP 8 fixes arrive.

Drupal

Drupal 10 sites can move from PHP 8.1 to 8.3 or 8.4 without changing Drupal's major version. Moving to Drupal 11 requires PHP 8.3 or newer. Drupal 7's security support ended on 5 January 2025, so a Drupal 7 site needs a migration to a current Drupal, or a replacement, not just a PHP change.

Joomla

Joomla 4 runs on PHP 7.2.5 and later, Joomla 5 on 8.1 and later, and Joomla 6 on 8.3 and later. Joomla 3 lost official support on 17 August 2023. Joomla 5.4.10, released 13 October 2026, is the last 5.x bugfix release, with security updates only for one more year.

When a Rebuild Costs Less Than an Upgrade

Sometimes the honest answer is that the old site cannot be upgraded economically. A rebuild is often cheaper when several of these are true:

  • The CMS itself is end of life, such as Joomla 3 or Drupal 7, so you face a migration anyway.
  • Key plugins or modules are abandoned and have no PHP 8 versions.
  • Custom code relies on functions PHP has removed, such as the old mysql_ functions, create_function() or each(), throughout.
  • Nobody who wrote the custom code is available, and there are no tests.
  • The site needs a redesign or accessibility work soon anyway.

A rebuild is also a chance to reduce how much PHP faces the public. A static or headless front end serves pages without running PHP for every visitor, which shrinks the exposure to the next PHP-level flaw. Our headless CMS development team can scope that work.

Conclusion

As of 23 October 2026, the safe end state for an old PHP site is PHP 8.3 or 8.4 on a patched build. Get there in order: patch or isolate today, inventory, back up, stage, update extensions, scan and test, then switch with a rollback that never lands on unpatched PHP. If the CMS is end of life or the code is beyond repair, price a rebuild before you sink time into an upgrade. If you need help with the urgent part or the whole project, our emergency PHP patching team can work through it with you. Every PHP2Shell guide is in our PHP2Shell Resource Center.

Frequently Asked Questions

How long does a PHP upgrade take?

It depends almost entirely on the code. A maintained WordPress, Drupal or Joomla site with current extensions can be a short, planned job. A site with abandoned plugins or old custom code can take much longer. Your inventory and staging tests will tell you.

Can I jump straight from PHP 7.4 to 8.3?

Yes. You do not need to stop at each version on the live site. You do need to account for every change from 8.0 through 8.3 when you test, because you absorb all of them at once.

Should I upgrade to PHP 8.2 because it is fixed?

Only as a short step. PHP 8.2.35 fixes PHP2Shell, but 8.2 reaches end of life on 31 December 2026, so you would repeat the upgrade within months. PHP 8.3 or 8.4 is a better target.

Will updating WordPress, Drupal or Joomla fix PHP2Shell?

No. The flaws are in PHP itself. CMS and plugin updates matter for the upgrade, but only a patched PHP fixes PHP2Shell.

Is a compatibility scanner enough to know my site will work?

No. Scanners read code without running it, and PHPCompatibility says its coverage is not 100%. Always test on a staging copy with error logging on.

What if the upgrade breaks my site?

Switch back to the old PHP version and restore your backup if needed, but only if the old version is a patched build. Otherwise, put up a maintenance page while you fix the problem on staging.

Is it cheaper to rebuild than upgrade?

Sometimes. If the CMS is end of life, key extensions are abandoned or the custom code uses removed PHP functions throughout, a rebuild on a current platform is often the better use of the budget.

Put this into action with eSEOspace

We help businesses grow with maintenance & support that actually performs. Explore the services behind this guide:

Book a free strategy call →

Get a FREE Audit

We'll perform a comprehensive SEO, AEO, GEO & CRO audit of your website — completely free — and show you exactly how to outrank your competitors.

Don't have a site yet? Get in touch →

Get a FREE GEO/AEO/SEO Audit

We'll analyze your site's SEO, GEO, AEO & CRO — completely free — and show you exactly how to get found across Google and AI answers.

Don't have a site yet? Get in touch →

You Might Also like to Read