Skip to content
Guide · WordPress

PHP 8.2 end of life: move WordPress to PHP 8.4 without the critical error

Security support for PHP 8.2 ends on 31 December 2026. If your WordPress site still runs on it, move before then. In most hosting panels, changing the version is a single setting. WordPress core runs on PHP 8.4, so a critical error after the PHP update almost always comes from a plugin, the theme or custom code, and you see "There has been a critical error on this website." Here is how to avoid that, and how to recover.

Close-up of a hand typing on a dark keyboard in low light.
Fabian Wagner, founder of Blax Software

Fabian Wagner, founder of Blax

Published

PHP 8.2 security fixesUntil 31 Dec 2026
Our default pickPHP 8.4
WordPress core on PHP 8.4Since 6.7

What the date means

According to php.net, security support ends on 31 December 2026 for 8.2, 2027 for 8.3, 2028 for 8.4 and 2029 for 8.5. PHP 8.6 is due on 19 November 2026.

Your site keeps running on 1 January, but the PHP project stops fixing 8.2. On 21 October 2026 it warned of two critical vulnerabilities that allow unauthenticated remote code execution, with 8.2.35 among the fixes. From January, a fix like that depends on your host.

In Austria, World4You and easyname sell a paid PHP Extended Support for outdated versions. Host Europe in Germany moves every 8.2 domain on its Classic Hosting platform to 8.4 on 9 November 2026. Customers can switch back to 8.2 until 7 December. Then Host Europe deactivates 8.2 and moves every remaining domain to 8.4 for good.

Extended support buys time. Your host keeps patching and you pay for it, but your plugins get no more compatible. Some updates already need more than 8.2: Contact Form 7 6.2.4.1 requires PHP 8.3, and on 8.2 WordPress only tells you "There is a new version of Contact Form 7 available, but it does not work with your version of PHP."

Who is affected

Mostly shared hosting sites where someone picked a PHP version years ago. WordPress itself is fine. The core handbook lists PHP 8.4 support from WordPress 6.7. Trouble comes from themes whose update licence ran out, abandoned plugins, custom code from a former agency, and two PHP 8.4 changes:

  • IMAP, OCI8, PDO_OCI and PSpell moved out of core PHP to PECL. A plugin that fetches mail over IMAP breaks unless your host installs the extension.
  • PHP 8.4 adds array_find(), array_find_key(), array_any() and array_all(). A plugin that declares its own array_find() without a function_exists() guard dies with "Cannot redeclare function".

To see where your site stands, open Tools > Site Health in the WordPress admin. On 8.2 it reports "Your site is running on an older version of PHP (8.2.x), which should be updated". The exact version is under Site Health > Info > Server.

The upgrade, step by step

We recommend 8.4. It takes the same work as 8.3 and gets security fixes a year longer. WordPress has supported 8.5 since 6.9, but plugins lag behind, and the core handbook lists no support for 8.6 yet.

No PHP setting in your panel, or no 8.4 on offer? Ask your host's support to switch the site, or to run a test copy on 8.4. If they only offer paid extended support, moving hosts is often the cleaner way.

  1. Back up. Database, wp-content and wp-config.php, with the dump outside the web root: mkdir -p ~/backups && wp db export ~/backups/before-php-84.sql. Without SSH, export the database in phpMyAdmin and download the files over SFTP.

  2. Make a staging copy with its own database. Copy the site to a new folder with its own subdomain and PHP setting. Not every host allows that. At World4You, for example, the PHP version is set for the whole webspace under Dein Paket > Webspace > Einstellungen. If yours works like that, ask the host for a temporary second package for the copy, or have us set up the copy for you. The copied wp-config.php still points at the live database, so create a new empty database and put its credentials into the copy's wp-config.php (DB_NAME, DB_USER, DB_PASSWORD, sometimes DB_HOST). Then, inside the copy's folder:

    bash
    wp config get DB_NAME   # must show the new database
    wp db import ~/backups/before-php-84.sql
    wp search-replace 'https://www.example.com' 'https://staging.example.com' --skip-columns=guid

    Without SSH, a migration plugin can do the import and URL replacement. To keep the copy from emailing customers or running scheduled jobs, add define( 'DISABLE_WP_CRON', true ); to its wp-config.php. Then create the folder wp-content/mu-plugins if it does not exist, and in it a file no-mail.php containing:

    php
    <?php
    add_filter( 'pre_wp_mail', '__return_true' );
    add_filter( 'action_scheduler_allow_async_request_runner', '__return_false' );

    On WooCommerce sites, the Action Scheduler also starts its queue whenever someone opens wp-admin, whether or not WP-Cron is disabled. The second filter stops that. Pause newsletter plugins that use their own sending service, and put the copy behind a password.

  3. Update, then switch the copy. Update core, themes and plugins as far as they install on 8.2. Then set the subdomain to PHP 8.4 and install the updates that need 8.3 or later, such as Contact Form 7. Write down the order: you repeat it on the live site in step 6.

  4. Scan the code. This step is for whoever looks after your code: run it on a computer with PHP and Composer, next to a downloaded copy of the site. Without those, skip to step 5. PHPCompatibilityWP checks plugin and theme code against a target PHP version. Its PHP 8 rules are still alpha releases, so Composer has to allow alphas:

    bash
    mkdir php-check && cd php-check
    echo '{}' > composer.json
    composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
    composer config minimum-stability alpha
    composer config prefer-stable true
    composer require --dev phpcompatibility/phpcompatibility-wp:"^3.0@alpha"
    
    vendor/bin/phpcs -p ../my-site/wp-content/plugins ../my-site/wp-content/themes \
      --standard=PHPCompatibilityWP --extensions=php --runtime-set testVersion 8.4

    In our test against a demo plugin it flagged imap_open() as an error but missed a self-declared array_find(). Linting every file under PHP 8.4 catches it. Check with php -v that the command line runs 8.4, then run find ../my-site/wp-content -name '*.php' -exec php -l {} \; 2>&1 | grep "Fatal error".

  5. Test the copy. Click through like a customer: contact form, checkout, login, admin, media upload. Then check the debug log, enabled as shown below, for "PHP Fatal error". Deprecation notices do not break anything on 8.4.

  6. Update live, then switch. Take a fresh backup and repeat on the live site what worked on the copy, in the same order. Copying the staging site over a shop would lose every order placed since you made the copy. Write down the old PHP version before you switch. At World4You the setting is under my.world4you.com > Dein Paket > Webspace > Einstellungen: pick 8.4 and click "PHP-Version wechseln". At Host Europe it is in KIS under Produktverwaltung > your product > Konfigurieren > Skripte & Datenbanken > PHP-Versionen.

  7. Test live. Repeat the round from step 5. Mail goes out for real now, so send a form to your own address and check that it arrives.

"There has been a critical error on this website"

If the error appears right after the switch, set the old PHP version back first, then debug on the staging copy.

WordPress also emails the admin address, subject "[Your site] Your Site is Experiencing a Technical Issue". The mail names the plugin or theme and links to recovery mode, which pauses the faulty extension for your session only. Visitors still see the error until you deactivate it. If the admin address is a dead inbox, set another one in wp-config.php: define( 'RECOVERY_MODE_EMAIL', 'tech@example.com' );. WordPress sends at most one such mail a day, and its link is valid for a day.

If no mail arrives, turn on the debug log. Add this above the "That's all, stop editing!" line in wp-config.php, replacing any existing WP_DEBUG line. The logs folder must exist and be writable by PHP:

php
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/home/your-user/logs/wp-debug.log' );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );

With true instead of a path, the log lands in wp-content/debug.log, where anyone can download it unless you block it. Turn debugging off once you have found the cause.

Without admin access, rename the plugin's folder over SFTP, or use WP-CLI:

bash
wp cli info   # the command line may run a different PHP than the site
wp plugin list --status=active --field=name --skip-plugins --skip-themes > active-plugins.txt
wp plugin deactivate broken-plugin --skip-plugins --skip-themes
wp plugin deactivate --all --skip-plugins --skip-themes          # emergency: everything off
wp theme activate twentytwentyfive --skip-plugins --skip-themes # if the theme is the culprit
wp theme install twentytwentyfive --activate --skip-plugins --skip-themes # if it was deleted

Then reactivate the plugins from active-plugins.txt one at a time with wp plugin activate <name> and reload after each.

When to get help

With SFTP access and a quiet afternoon you can do most of this yourself. Get help when the broken plugin is business-critical and abandoned, when your shop sells around the clock without a staging copy, when there is no way back to 8.2, or when your host has no 8.4 or only sells extended support.

As a WordPress agency in Linz, we fix broken plugins instead of telling you to buy a different one. See bugfixing, maintenance and optimization for what we take on. If your host is the problem, we move the site to our hosting, test it on the new server and switch over once everything works.

A short call costs nothing. Tell us through the contact form which PHP version your site runs and which plugins worry you. We usually reply within one business day.

Curious how this plays out in practice?

These essays are the why. The how shows up in the projects we ship. Drop us a note and we can talk about your specific case.