Moving from PHP 8.0 to 8.1 sounds like a small step. I still want to know what changes for the actual WordPress installation, rather than assume that a minor version number means there is nothing worth testing.
The useful distinction is between an application appearing to run and its code respecting the language's contracts. Deprecation notices are particularly interesting here. They can expose assumptions that have been tolerated for years, well before those assumptions become a more disruptive problem.
In this tutorial: What we are checking; Before you start; 1. Look for null values reaching string functions; 2. Check classes implementing internal interfaces; 3. Test the code that runs later; Check the result.
What we are checking
This guide concentrates on a WordPress site's behaviour under PHP 8.1, including code that may already work under PHP 8.0. It follows the same staging discipline as my PHP 8 compatibility checklist, with a narrower set of language changes to examine.
WordPress 5.9 and 6.0 include work towards PHP 8.1 compatibility. Core's support does not certify the combination of plugins, theme code and server extensions on an individual site.
Before you start
Keep a private staging environment with a documented baseline. Record both web and command-line PHP versions: a scheduled command can use a different executable from the website's PHP worker.
Protect real users from staging side effects. Use safe mail, payment and integration destinations, and restrict access to any copied private data. Keep a recoverable backup and a route back to the previous runtime.
1. Look for null values reaching string functions
PHP 8.1 deprecates passing null to non-nullable parameters of built-in functions in coercive mode. A field that is sometimes absent can therefore produce a notice where older behaviour quietly converted the value.
I want to decide what an absent value actually means. For an optional label, an empty string may be the intended result. For a required identifier, silently substituting an empty value could hide a broken import.
function cn_optional_label($value): string
{
if ($value === null) {
return '';
}
if (!is_string($value)) {
throw new InvalidArgumentException('Expected a text label.');
}
return trim($value);
}
This is a small teaching example, not a filter to apply indiscriminately across a site. The boundary calling it needs to handle invalid input. I would fix the model or validation that supplies the value before scattering defensive conversions through templates.
2. Check classes implementing internal interfaces
PHP 8.1 introduces tentative return types for many internal methods. A custom collection implementing an interface needs to respect that contract. For example, a class implementing Countable should make its count method's return type clear:
final class CnItems implements Countable
{
private array $items;
public function __construct(array $items)
{
$this->items = $items;
}
public function count(): int
{
return count($this->items);
}
}
The example requires PHP 7.4 or later because it uses a typed property. For maintained dependencies, I first look for the vendor's compatible release instead of editing vendor files by hand.
The ReturnTypeWillChange attribute can be a temporary compatibility measure in suitable code. It is not a reason to suppress every deprecation without understanding which contract needs changing.
3. Test the code that runs later
I repeat content editing, uploads, form validation and the relevant business journeys. I also check command-line tasks and scheduled imports under their intended PHP executable.
Those later jobs are easy to miss during an upgrade. A website can look healthy while a background process has stopped refreshing its data. I want evidence that a job completes, handles a controlled failure and leaves useful private diagnostics.
Check the result
Compare PHP 8.0 and 8.1 using the same application version and representative data. Review deprecation, warning and fatal-error categories separately. Do not turn off logging merely to obtain an empty report.
If a third-party component is not ready, I would document the dependency and wait or replace it deliberately. A server upgrade is not improved by leaving the client with a plugin nobody can maintain.
What I want from the exercise is a smaller list of assumptions. Finding one in staging is useful: it gives me time to understand the data and repair the code before the change becomes a production problem.
References
PHP documents 8.1 deprecations and backward-incompatible changes separately. WordPress's preparation note for 6.0 describes its compatibility context.