Upgrading a WordPress site, plugin, or theme to a new version of PHP is a task that recurs regularly. But how do you do this as efficiently as possible? How do you know you won’t overlook anything? Is there a roadmap for it?
In this article, we’ll tackle these questions (and more) and look at what’s involved in a smooth transition to PHP 8.x for your WordPress site, plugin, or theme, including a roadmap.
We’ll do this based on an interview we conducted with PHP expert Juliette Reinders Folmer. She devotes most of her daily life to programming and everything around it, focusing mainly on open-source projects, including WordPress.
Are you ready to make the switch smoothly too? Curious about our step-by-step plan? Then let’s dive right in!
PHP 8.x — What’s Changed
For an overview of the changes, we recommend the articles below:
- Release notes for PHP 8.0 and PHP 8.1
- Migration guide for PHP 8.0 and PHP 8.1
- WordPress and PHP 8.0 and current status
- What’s New in PHP 8.0 and PHP 8.1
- What’s New in PHP 8.2 and PHP 8.2 migration guide.
After reading these articles, you will be completely updated on what has changed in PHP 8.x and what you need to do to get your PHP projects running without any problems.
If you’re unsure what the best way to start is, no problem. In the conversation with Juliette, we discussed this in detail, and we will explain to you in this article as fully as possible how you can switch to PHP 8.x.
We will also explain in informative boxes how to perform various operations in MyKinsta, our proprietary control panel for all your WordPress sites, applications, and databases.
Switching to PHP 8.x: How To Get Started
Switching to PHP 8.x sounds simple, and technically, it is. Many hosts allow you to specify which version of PHP you want to use for your website in the admin panel. At Kinsta, switching the PHP version can be done with a single click in the MyKinsta dashboard.
But before you do, there are some things you need to be sure of. Depending on your level of knowledge and experience, we recommend the following:
- If you have built your own WordPress site with standard themes and plugins, without having much knowledge of PHP, hire a developer or agency to investigate whether your site is suitable to run on PHP 8.x. Are you looking for a third party that can help you with this? Then look at our Partners page listing several trusted companies that can assist you.
- If your WordPress site was built by an external party, a developer, or an agency, contact them to ask if your site can run on PHP 8.x.
- If you have built your WordPress site — with your own custom theme, for example, or self-developed plugins — we have a roadmap for you below.
If your site falls into one of the first two categories, we certainly invite you to read through the rest of the article, but we don’t recommend you start testing your site for PHP 8 compatibility yourself. Leave it to the professionals.
Whatever you choose, we would advise you not to just switch your live site to PHP 8 and “see if it works.” Are you curious about what your site will look like, and you can’t wait to see it running on PHP 8? Then start testing within a staging environment. A good host will allow you to easily set up a staging environment.
In the staging environment, you can activate PHP 8.x and see if this update works well with your site. It is also possible to work with a local copy of your site. With our free DevKinsta development tool, you can easily import your site from the MyKinsta dashboard, after which you can change the PHP version to 8.0 or 8.1.
If you don’t see any problems in the staging environment, it doesn’t necessarily mean there aren’t actually any problems. The roadmap below will tell you why.
PHP 8.x Compatibility Testing: The Roadmap
Testing: the keyword to good software. Even for WordPress websites and their components, such as themes, plugins, and the WordPress core, testing is the means to ensure that things don’t happen that you don’t want to happen.
A software development project consists largely of testing. In this article, we look specifically at the tests that can help you make the transition to PHP 8.x go smoothly. In our article on DevOps Tools, you’ll find a section with a collection of tools you can use.
The following types of tests are discussed in this blog post:
Let’s look more closely at the different types of tests we can perform.
Static Analysis (or Static Testing)
The first step you can take as a PHP developer is to perform a static analysis of your code with various tools. Static analysis is the process of analyzing software without executing the code. With static analysis, it is possible to detect errors, detect problems with PHP 8.x compatibility, enforce coding standards (for example, the WordPress Coding Standards), and even modifying and cleaning up the code is possible.
Tools for Static Analysis
You can perform a static analysis with various tools, such as:
At the time of writing, not all PHP 8.1 checks are supported in the latest PHPCompatibility release. PHP 8.1 checks can be in the development release, so make sure you use those (for now) when using PHPCompatibility to analyze your project and see what errors/recommendations there are.
PHP 8.1 checks will soon be released in a new major version. If you want to be kept up to date on this, and you have a GitHub account, open GitHub repository of PHPCompatibility and navigate to Watch -> Custom -> Releases, where you can choose to be notified when a new version is released.
PHPCompatibility, which only tests compatibility for a particular version (or range of versions) of PHP, is easy to set up. You get the best results if you run a testVersion — for example, 8.0+ (8.0 and up) — within PHPCompatibility.
You should be looking out for deprecated or deleted functions, changed default values of function parameters, whether to use concat without parenthesis, whether to use match as a function name (since it has been reserved since PHP 8.0), etc.
Psalm and PHPStan are good additions and can help you by performing additional checks related to variable types. The downside of these tools is that it takes a lot of configuration to get reports on PHP 8.0 and 8.1. Even if they are successful, you can expect many false positives. False positives are notifications that are given wrongly, caused by the limitations of static analysis.
Sound knowledge is required to properly interpret the results of these two tools, but that knowledge can help you identify additional incompatibilities that PHPCompatibility cannot find. Look at the documentation for Psalm and PHPStan if you want to learn more about them.
- Perform static analysis with PHPCompatibility, Psalm, PHPStan
- Resolve all legitimate problems
The next step in the process is unit testing. Unit testing is a method of testing pieces of code individually. In unit testing, specific targeted tests will be developed for each unit. This will involve running through different scenarios. Preferably, each scenario is tested separately from the others so that the tests are independent of one another.
Supporting Multiple Versions of PHP
As a plugin builder, if you want to support multiple PHP versions, ensure the tests in CI are run against all PHP versions you support.
Of course, you can also support only newer versions, the choice is entirely up to you.
Testing with multiple versions of PHP requires that you use multiple PHPUnit versions, depending on the PHP version. Since PHPUnit has introduced several changes over the years that affect how tests are written, this part can be tricky.
To get around this, you can use the PHPUnit Polyfills (written by Juliette and sponsored by Yoast). This lets you write tests that are officially unsupported for PHPUnit 9 (and thus can run on PHP 8.x). The Polyfills then make your tests work in PHPUnit 4.x through 9.x and with PHP 5.4 through PHP 8.1 (as of now).[/notice]
Now that you have the tests running, the next step is to make sure the problems found in the tests are fixed.
Running these tests is the most reliable way to find cross-version incompatibilities.
In doing so, pay attention to the code coverage of your tests:
- Suppose you have a function A and have written a test for it, and function A call functions B, C, and D as part of the logic in the function.
- The test for function A is written to test the logic of function A, but it will also call functions B, C, and D during testing. For functions B, C, and D, you then usually only test the “happy path” — the situation where everything goes well — and thus, those functions are also not yet fully tested, although (part of) the code in those functions is executed during the testing of function A.
- For each of your tests, indicate which code is specifically being tested. You do this by giving each test a @covers. This way, B, C, and D are not “counted” in the code coverage calculation, which allows you to see what part of your code is covered by tests.
Often developers write and test — sometimes even unknowingly — for the “happy path.” In these cases, testing what happens when unexpected data is passed to a function is also necessary. Testing with only expected values/types is not enough.
The second part of the above quote is often forgotten, when it is perhaps even more important than the first part. What happens if you pass an incorrect type? Do you get an error message? Or is the variable cast with the function continuing as normal? What if an unexpected value is passed to the function?
Be sure to test your functions with unexpected variables, types, and values. Only then can you rely on your tests to find problems that a new PHP version may cause.
PHP Is Getting Stricter
PHP is becoming more precise (strict) in how it handles “types” for PHP’s own functions, as well as things like dynamic properties. These changes are generally intended to help developers deliver error-free code (well, code with fewer errors). But this can present quite an upgrade hurdle for pre-existing code written based on the “old” tenets of PHP.
Because of this drive for more helpful error messages in PHP, you can see that making existing code suitable with new PHP versions takes more and more time. Making code that worked on PHP 5.6 suitable for PHP 7.0 only took a fraction of the time in most cases compared to upgrading code to make it suitable for PHP 8.1. And that’s despite the fact that PHP 7.0 was a “major” release, while PHP 8.1 is a “minor.”
In many cases, testing is still the only reliable way to determine what needs to be modified to support a new version.
Unit testing is possible with various tools, including:
Many of these tools are built based on, or in conjunction with, PHPUnit.
Ultimately, it doesn’t matter what tools you use. The most important thing is that you test, and get the tests running on new PHP versions. This step can sometimes be very tricky, but fortunately, as mentioned earlier, there are tools for this, such as PHPUnit Polyfills.
Integration testing is the next step we will perform, after static analysis and unit testing. An integration test is where real-life situations are tested in a larger context than just a “code unit.” These include testing with an active (test) database or testing with an external API, to give just two examples.
So, when you test the code of a plugin or theme in the context of WordPress and use a real version, these are, by definition, integration tests.
WP Test Utils (again written by Juliette and sponsored by Yoast) is an excellent tool for integration testing. WP Test Utils provides tooling to write integration and unit tests, in which WordPress is “mocked up” using Brainmonkey and Mockery, where commonly used WordPress functions are “faked” so that you are testing your own code and not the WordPress code.
Integration testing with WordPress is a trickier story because it involves integration with WordPress and WordPress’ test suite. Depending on which versions of WordPress a plugin or theme supports, you have to consider which PHPUnit versions are supported by WordPress itself to run the tests on different PHP versions.
For example, WordPress 5.6 through 5.8 uses PHPUnit 5 through 7 for testing PHP 5.6 through PHP 8.0, but as of WordPress 5.9, WordPress itself also uses PHPUnit Polyfills for broader support. WP Test Utils acts as a bridge to overcome all these differences.
Want to learn more about how to run integration tests against multiple different versions of WordPress, including WordPress 5.9 and above? Then read about it on WordPress’ website.
Now that you’ve gone through unit testing and integration testing and have fixed all the issues you found, it’s time to do manual testing. Your site is running, and your own code is working, but you’re also using plugins A, B, and C. Do you know if those plugins are compatible?
For example, check this with the plugin’s authors and see if they indicate that it is PHP 8.x compatible. The question then, of course, is how the plugin was tested. Often the answer here is: in isolation. The plugin’s functions have usually been tested in conjunction with WordPress alone, without other active plugins. And even if other plugins were used within these tests, chances are that not all plugins used by you were part of the testing, so take such a compatibility statement with a grain of salt.
For example, a WordPress site with 3 plugins (A, B, and C). It’s possible that plugin B, for example, returns an incorrect variable type via a filter, which plugin C, using the same filter, wants to work with. This can then cause a fatal error because the type is no longer what is expected. Plugin C is then seen as the culprit for the error message, even though plugin B is the real offender.
Plugin interoperability-incompatibilities are impossible to discover when testing in isolation. The more active plugins, the more likely something will go wrong. For example, it would be very beneficial to pass page requests from a live website to a staging environment (with error logging enabled) to discover what is actually going wrong.
With this type of problem, a site owner will usually only see a message that there was an error with the last executed code (in this case, from plugin C), even though plugin C is not necessarily the cause of the problem.
In most cases, a lot of manual, human work is involved, and a healthy amount of elbow grease is required to detect and fix these problems. This could be automated using end-to-end testing, but we don’t see this happening much in WordPress.
Test Availability for Utilized Plugins
For developers and development teams: Accept code only when tests are available. This way, you ensure that less manual testing is required, which saves you a lot of time.
Question its testing strategy if you want to buy a commercial plugin or theme. That way, we collectively create awareness among developers/development teams in the WordPress community to get testing higher on the agenda, and we all benefit.
Testing is often viewed — unfairly — as a cost when, in reality, it saves money. The extra investment required to write tests pays off in the form of significantly fewer bug reports and less time spent fixing bugs. In addition, with automated software testing, extensions and modifications can be done faster because the tests can speedily confirm that existing functionality continues to work.
The Role of WordPress Hosts and PHP 8.x
For the average site owner, guidance from your host is highly desirable. Consider the following:
- Documentation and updates for customers that WordPress Core, plugins, and/or themes are (in some cases) not PHP cross-version compatible
- Options for testing (such as working with a staging environment)
- Methods for error reporting and contacting support
This also benefits a web host, as site owners often contact the host for help when problems arise. In the case of a switch to PHP 8.0, 8.1, or 8.2, the site owner is responsible for potential problems, and the more information the owner has to properly prepare for the switch, the better.
Making PHP 8.1 or 8.2 available to customers as a web host is one thing, but in doing so, they must make sure to create awareness among customers so they’re aware that problems might surface. Testing your site in a staging environment with a different version than live is recommended. (Selecting PHP versions is available by default at Kinsta.)
Minimum PHP Version for WordPress
Over 15% of all websites currently use PHP version 7.0 or lower. This can be seen in the official WordPress statistics. About 83% of all WordPress sites currently use PHP version 7.4 or lower. Please note that anything lower or equal to version 8.0 is currently no longer supported by PHP. Using end-of-life versions of PHP can result in problems because security updates are no longer released.
To avoid problems, it’s important that WordPress site owners are aware of and informed on the minimum PHP version that will allow their site to run safely. For their part, site owners can modify the PHP version themselves (possible at Kinsta for all packages) or ask their host to update the site to a newer PHP version. In extreme cases, you can switch to a host that supports these newer versions.
Because WordPress only requires a minimum version of 7.4, there is insufficient motivation for many hosts and website owners to update their sites. And this is despite the fact that PHP 7.4 reached its end-of-life in November 2022.
If WordPress ever does increase the minimum PHP version, this may mean that many sites will no longer be compatible with an update to the latest WordPress version. However, security updates will continue to be released for those outdated versions for quite some time.
To switch to PHP 8.0 or higher for your website, there are several steps that you, or your developer, must perform. Important steps include:
- Static analysis
- Unit testing
- Integration testing
- Manual testing
When switching to PHP 8.x, ensure everything has been properly tested. This is the only way to guarantee that your site will run properly, quickly, and securely on a newer PHP version.
We thank Juliette immensely for participating in this article and for all her work on the tools mentioned!
Photo of Juliette, taken by Jip Moors and used with permission.