Upgrade to PHP 7.3 for Better WordPress Performance and Security

Renovation by Milivoj Kuhar

If you are running WordPress on any ancient PHP version older than 5.6, I have some bad news for you: as of WordPress version 5.2, the minimum PHP version that WordPress runs on is 5.6.20. Don’t sigh from relief even if you are running PHP 5.6 or even 7.0 and your site seems to work fine. Aim to update to the newest version 7.3 as soon as possible even if the WordPress core does not explicitly force you to do so. We’ll explain why and how in this article.

My site already works – why the hassle?

The unfortunate news is written on the PHP website: PHP versions earlier than 7.1 no longer receive security updates. This means that discovered security flaws in the PHP programming language are no longer fixed in those versions. This makes your site vulnerable to potential attackers. The security updates for PHP version 7.1 will also end at December 1st 2019, so upgrading your sites to use the newest PHP version 7.3 would definitely be a move worth considering.

If you still happen to be running a PHP version below 7.0, migrating to PHP 7 will also make your site up to 3-4 times faster and adds a multitude of features to make the lives of developers easier, which we have described in our blog post regarding the launch of PHP 7.3.

For the true PHP geeks out there, PHP 7.4.0 alpha 1 has also just recently been released at June 13th 2019, but it is currently at an early test version which is not suitable for production use. PHP 7.4.0 is scheduled for general availability (GA) at the end of November 2019, just before PHP 7.1 support ends in December. PHP 7.3 will be supported until December 6th 2021, so there is no need to worry about its support ending soon.

To make upgrading your site to PHP 7.3 as convenient as possible, we have included a brief example of the process with a demo site.

Verify your current PHP version

The starting point of our PHP version upgrade is a production site that is running PHP 5.6. If you are not sure which PHP version your web server is currently running, it makes sense to check it first to verify whether an upgrade is needed. Seravo.com customers can check their PHP version by our custom script wp-check-php-version, which will also inform about PHP version deprecation if using an old version:

leotoikka@leotoikka_02d27b:~$ wp-check-php-version
 Checking for PHP backends…   
 Using default PHP mode (php5)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
 ! WARNING: PHP 5.6 is deprecated, security support has ended 31th December 2018!!   
 ! 
 !
 ! See https://seravo.com/docs/configuration/php7-hhvm/ for more details. !  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 php5

Some web hosting providers provide the information in an administration panel, for instance CPanel. If you know you are running PHP with PHP-FPM (FastCGI), you can also look for which PHP process is running with the following command, and look for a php-fpm process if you are running:

leotoikka@leotoikka_02d27b:~$ ps aux | grep 'php' | grep -v grep
...
leotoik+ 17091  0.0  0.0 399804 29640 ?        Ss   10:13   0:00 php-fpm: master process (/etc/php/5.6/fpm/php-fpm.conf)
...

However, be careful when checking the PHP version via cli with php -v as the CLI installation of PHP is separate than the one your web server runs and may differ with regards to version.

Either way, if the results of the command you ran indicated that you are running a version below 7.1, you should seriously consider upgrading it to a newer version. We will guide you through the process in-depth in the following sections so you can avoid the most common pitfalls during the process.

Check for Incompatibilities in PHP Code

Checking for PHP version compatibility is usually done by static code analysis by using different code sniffing tools. For this, Seravo.com customers have a wp-php-compatibility-check script available in their instances. It can be run when logged in via SSH. The script takes the path and PHP as parameters and runs PHP_Codesniffer under the hood together with PHPCompatibility, both of which are open source software. In this case, we are checking for PHP 7.3 incompatibilities in the wp-content directory as it includes all plugins and themes, and we assume that your WordPress core version is compatible with PHP 7.3. If you are using an old version of the WordPress core, you should proceed to update it first.

leotoikka@leotoikka_51ac74:~$ wp-php-compatibility-check
............................................................  60 / 453 (13%)
............................................................ 120 / 453 (26%)
............................................................ 180 / 453 (40%)
............................................................ 240 / 453 (53%)
.......................................................W.... 300 / 453 (66%)
......W...............W.........W..............W............ 360 / 453 (79%)
...............EE.WWW....................................... 420 / 453 (93%)
.................................                            453 / 453 (100%)



FILE: /data/wordpress/htdocs/wp-content/plugins/polylang/include/model.php
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 2 WARNINGS AFFECTING 2 LINES
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 613 | WARNING | Since PHP 7.0, functions inspecting arguments, like debug_backtrace(), no longer report the original value as passed to a parameter, but will instead provide the
     |         | current value. The parameter "$func" was used, and possibly changed (by reference), on line 576.
 630 | WARNING | Since PHP 7.0, functions inspecting arguments, like debug_backtrace(), no longer report the original value as passed to a parameter, but will instead provide the
     |         | current value. The parameter "$func" was used, and possibly changed (by reference), on line 576.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


(SOME OTHER WARNINGS...)


FILE: /data/wordpress/htdocs/wp-content/plugins/wp-native-dashboard/wp-native-dashboard.php
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FOUND 2 ERRORS AND 2 WARNINGS AFFECTING 4 LINES
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  90 | ERROR   | Function split() is deprecated since PHP 5.3 and removed since PHP 7.0; Use preg_split() instead
 105 | WARNING | Use of deprecated PHP4 style class constructor is not supported since PHP 7.
 541 | WARNING | Method name "wp_native_dashboard::__list_versions_by_de_de" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.
 547 | ERROR   | Function split() is deprecated since PHP 5.3 and removed since PHP 7.0; Use preg_split() instead
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


(SOME OTHER WARNINGS...)


Time: 50.42 secs; Memory: 107Mb

Scan complete. Results are stored in the logfile /data/log/wp-php-compatibility.log

The script outputs information about the PHP version incompatibilities it finds: the filename, line within the file, the type of the result and a message that describes what is wrong and how to fix it. There are two types of results in the output of the command: warnings and errors. Warnings are not as crucial as errors, which will most likely break your site at least in part. For instance, the error Function split() is deprecated since PHP 5.3 and removed since PHP 7.0; Use preg_split() instead indicates that changing to a PHP version larger than 7.0 would cause the function split() that the plugin uses to disappear, causing a PHP fatal error when that code is run the site.

Take Extra Precautions

As there always exists a risk with software version upgrades that something goes wrong and your site faces downtime, it is highly recommended to test the PHP version upgrade in a server that is separate from your production server first. This way, production site downtime is avoided and the users of your site will not be affected at all.

In this demonstration we will use a staging instance provided for Seravo.com customers to test the migration before actually proceeding to doing it in production. However, any WordPress site in an environment that is as identical as possible to your production environment will do. If you do not have access to staging instances or you have already performed a PHP version incompatibility scan with clean results, you may also proceed to upgrade the PHP version in production with maintenance mode activated.

If you do not have access to staging instances or you have already performed a PHP version incompatibility scan with clean results, you may also proceed to upgrade the PHP version in production during with maintenance mode activated.

To make sure the instance is identical with the current production, we will reset it the to the newest production state with our wp-shadow-reset script that is available in all production instances of Seravo.com customers:

leotoikka@leotoikka_02d27b:~$ wp-shadow-reset leotoikka_51ac74
Warning: the database and all files in /data/wordpress in shadow leotoikka_51ac74 will be deleted and replaced with a clone from production. Are you sure you want to proceed? (y/n): y
Exporting production database...
Moving database from production to leotoikka_51ac74...
Moving files from production to leotoikka_51ac74...
Importing production database to leotoikka_51ac74...
Success: the shadow leotoikka_51ac74 has been updated with production.

Before exiting the production instance and entering staging to proceed with the upgrade, take a fresh backup of your production site to ensure that a fallback plan exists in case something goes wrong in the process:

leotoikka@leotoikka_02d27b:~$ wp-backup
--> Dumping database contents into /data/db/leotoikka_02d27b
Success: Exported to '/data/db/leotoikka_02d27b.sql'.
--> Creating backup of /data...
---> Common cache files, backups made by other software and other unnecessary files were excluded from the backup
---> Clean away old backups...
No increments older than Sun May 19 10:38:39 2019 found, exiting.
--> Backup completed
Successfully backed up 181 MB of data.
Backups at /data/backups contain now 32 increments with the oldest timestamp Mon May 20 01:03:02 2019

Resolve the Incompatibilities

Now we will move to the staging instance to resolve the incompatibilities. The PHP version incompatibilities that the script found originate from the plugins WP Native Dashboard and Polylang. The first thing to consider with PHP version incompatibilities due to third-party plugins or themes is whether they have updates available that fix the incompatibilities with newer PHP versions.

You should never modify the files of a third-party plugin or theme directly on your web server as your modifications will be overwritten when the plugin or theme updates. Instead, you should contact the plugin author about the problem. If you are a developer and the plugin you are using is open source, you may also participate in its development by adding a fixing patch to it.

You should never modify the files of a third-party plugin or theme directly on your web server as your modifications will be overwritten when the plugin or theme updates.

The availability of plugin updates can be checked easily and quickly with the handy WordPress Command line interface tool (WP CLI) if your server has it installed:

leotoikka@leotoikka_51ac74:~$ wp plugin list
+-----------------------------------+----------+-----------+---------+
| name                              | status   | update    | version |
+-----------------------------------+----------+-----------+---------+
...
| polylang                          | active   | available | 2.4.1   |
...
| wp-native-dashboard               | active   | none      | 1.3.12  |
+-----------------------------------+----------+-----------+---------+

Another option is to use the WordPress administration screen plugin page at https://example.com/wp-admin/plugins.php. Based on the output from WP CLI, it looks like there is an update available for the Polylang plugin. Let’s install the update directly now that we are in the staging instance:

leotoikka@leotoikka_51ac74:~$ wp plugin update polylang
Otetaan käyttöön ylläpitotila...
Ladataan päivitystä osoitteesta https://downloads.wordpress.org/plugin/polylang.2.5.4.zip...
Tiedoston polylang.2.5.4.zip aitoutta ei voitu todentaa koska digitaalista allekirjoitusta ei löytynyt.
Puretaan päivitystä...
Asennetaan viimeisintä versiota...
Poistetaan lisäosan vanhaa versiota...
Lisäosa päivitetty onnistuneesti.
Poistetaan käytöstä ylläpitotila...
+----------+-------------+-------------+---------+
| name     | old_version | new_version | status  |
+----------+-------------+-------------+---------+
| polylang | 2.4.1       | 2.5.4       | Updated |
+----------+-------------+-------------+---------+
Success: Updated 1 of 1 plugins.

Unfortunately, there are no updates available for the WP Native Dashboard plugin as it has last been updated 6 years ago. It makes sense to switch this abandoned plugin to something actively in development. A suitable replacement can be searched for in the WordPress plugins repository (or in the case of themes from the WordPress themes directory). In our example the plugin is no longer needed, so it can be uninstalled with wp plugin uninstall wp-native-dashboard --deactivate.

Now let’s run the PHP compatibility check again:

leotoikka@leotoikka_51ac74:~$ wp-php-compatibility-check
............................................................  60 / 448 (13%)
............................................................ 120 / 448 (27%)
............................................................ 180 / 448 (40%)
............................................................ 240 / 448 (54%)
........................................................W... 300 / 448 (67%)
.......W...............W.........W..............W........... 360 / 448 (80%)
............................................................ 420 / 448 (94%)
............................                                 448 / 448 (100%)



FILE: /data/wordpress/htdocs/wp-content/plugins/polylang/include/model.php
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 2 WARNINGS AFFECTING 2 LINES
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 613 | WARNING | Since PHP 7.0, functions inspecting arguments, like debug_backtrace(), no longer report the original value as passed to a parameter, but will instead provide the
     |         | current value. The parameter "$func" was used, and possibly changed (by reference), on line 576.
 630 | WARNING | Since PHP 7.0, functions inspecting arguments, like debug_backtrace(), no longer report the original value as passed to a parameter, but will instead provide the
     |         | current value. The parameter "$func" was used, and possibly changed (by reference), on line 576.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


(SOME SIMILAR WARNINGS...)


Time: 49.3 secs; Memory: 107Mb

Scan complete. Results are stored in the logfile /data/log/wp-php-compatibility.log

There are still some warnings from the Polylang plugin, but they do not seem very critical. The plugin is quite popular, in active development and the plugin code is automatically tested to be compatible with PHP 7.3 by Travis CI, so we will continue to proceed to change the current PHP version to PHP 7.3 in the staging instance despite warnings. Seravo.com customers have a custom guide for selecting the active PHP version to refer to, otherwise turn to the documentation or customer support of your hosting provider.

Testing Before Upgrading Production

After you have upgraded your web server to use PHP 7.3 in your staging instance, some testing is necessary to verify that nothing is broken. You might want to run acceptance tests to verify that the site works properly. If you’re a Seravo.com customer you have access to an acceptance testing suite by simply running the command wp-test.

leotoikka@leotoikka_51ac74:~$ wp-test
I: Starting wp-test-ng...
I: Using URL 'https://leot.fi' for pre-flight checks.
I: Using shadow cookie with hash 51ac74
I: Pre-flight test for https://leot.fi returned HTTP code 200
I: Executing ChromeDriver...
Starting ChromeDriver 74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}) on port 9515
Only local connections are allowed.
Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
I: Ensure test user exists...
I: Updated permission and password for existing test user...
I: Running Codecept test suite 1/1..
Codeception PHP Testing Framework v3.0.0
Powered by PHPUnit 6.5.14 by Sebastian Bergmann and contributors.
Running with seed:


Acceptance Tests (2) ---------------------------------------------------------------------------------------------------------------------------------------------------------------
⏺ Recording ⏺ step-by-step screenshots will be saved to /data/reports/tests/
Directory Format: record_5d08d112094be_{filename}_{testname} ----
✔ SeravoCheckWPHomeCest: Try to open home (3.81s)
✔ SeravoCheckWPLoginCest: Try to login and access wp admin (9.17s)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
⏺ Records saved into: file:///data/reports/tests/records.html


Time: 14.14 seconds, Memory: 16.00MB

OK (2 tests, 4 assertions)
I: Lower test user privileges as test ended...
I: Finished running wp-test-ng

As the acceptance testing system cannot test everything, manual testing should also be done. The simplest way to do this is to follow the output of your PHP error log by tail -fn 0 /data/log/php-error.log and browsing the site simultaneously.

After you have walked through the site successfully without any errors and loss of functionality anywhere, you can be pretty certain that your site works with PHP version 7.3. Consider performing the upgrade in your production instance when it’s low on traffic, for instance at night or early morning. That way you should have a working end result with minimal production downtime. There is nothing to worry about should something go wrong, as the production backup that you took in the beginning of the process can be restored easily.

Not sure where to start or worried about breaking something? If you are a Seravo.com customer, no worries: our experts will gladly perform the PHP version upgrade for you.