How to Prepare Your WordPress Site for PHP 8

How to Prepare Your WordPress Site for PHP 8

WordPress sites require PHP, and as PHP has evolved, WordPress has kept up. Most recently, PHP 7.4 has been the default version of PHP on the WordPress VIP Platform. However, as PHP 7.4 comes to the end of its security support in November 2022, WordPress sites will need to upgrade to maintain strong security. For this reason, the WordPress VIP platform will be moving all of our customer applications to run on PHP 8.0.

What follows is a description of the changes, and the steps that both our customers and others using WordPress on other platforms can do to prepare.

Table of contents

The PHP 8.0 story

Released in November 2020, PHP 8.0 provided several enhancements and features that made new code (and shorter code) more resilient against bugs.

Most developers will find substantial benefits in PHP 8.0. However, as a major version, it does contain several breaking changes. This makes the switch from PHP 7.4 to PHP 8.0 trickier than, for example, the change from PHP 7.3 to PHP 7.4. Specifically, there were 49 breaking changes to core PHP, and 169 throughout PHP 8 overall, including in libraries and extensions that your code may rely on.

The good news is once organizations move to PHP 8.0 they will receive security support from the core PHP project until November 2023. After that date, an organization will need to upgrade to PHP 8.1, a minor release requiring a much smaller change.

New features

PHP 8.0 was designed to 1) fix edge cases and inconsistencies to make PHP a more solid and predictable scripting language, and 2) provide new features to improve the language overall. These include several new syntaxes that:

  • Make it easier to write strictly-typed code, for example, union types, static and mixed types, Stringable interface, and changes in the handling of numbers.
  • Reduce the amount of code you have to maintain, for example, nullsafe operator, constructor property promotion, match operator, and non-capturing catches.
  • Simplify code such as allowing ::class on objects, trailing comma in parameter lists, str_contains(), str_starts_with(), and str_ends_with() functions, throw expression, attributes.

It also includes Named Parameters. However, it’s worth noting WordPress core does not claim compatibility with this feature. So while you can call your own custom functions with named parameters, you shouldn’t call WordPress functions, as the parameter names may change without warning in the future.

Proliferation of support throughout the PHP and WordPress communities

Whenever a new version of PHP is released that includes new syntax, it takes time for the new syntaxes to be supported throughout the PHP and WordPress communities.

PHP developer tooling

PHP development tools such as Composer, PHPUnit, PHP_CodeSniffer, PHPStan, Xdebug, and various IDEs all need to recognise the new syntaxes of a new version of PHP. While PHP is continuously being developed there can be a lag time before the full ecosystem around a new version is available. Often, however, tooling can be ready to go by the time the final release is ready because development work has happened based on alpha, beta, and release candidate releases that have been made available ahead of time. All of these tools and more now support PHP 8.0, which makes it a good choice for developing PHP code and specifically for developing WordPress.  

WordPress core

Next, WordPress core needs to support PHP 8.0. The WordPress project has a long history of compatibility with new versions of PHP by the time they are released. Per this well-written post on Make WP, WordPress has had “beta compatibility” with PHP 8.0 since the WordPress 5.6 release in December 2020. What does “beta compatibility” mean? It means that WordPress can run fine on PHP 8.0, but features like declaring strict types in WordPress core files, or using named parameters with WordPress core functions, are not supported.

WordPress VIP platform

The WordPress VIP platform has supported PHP 8.0 (and PHP 8.1) since May 2022, including the suite of plugins and features that allows the platform to meet enterprise needs. 

Third-party plugins

WordPress has tens of thousands of plugins, and the level of support for PHP 8.0 varies widely. For example, newly reserved words might still be used by a plugin, or parameters being passed to PHP native functions might not be of the type that is now expected.  As such, third-party plugins may be one area where incompatibilities with PHP 8.0 could impact your application.

Below you can learn how to check for some of these incompatibilities. Options include asking the upstream individual/team to do the fixes and make a new release, or having an in-house development team or an agency, like one of our featured partners, fork the plugin and make the fixes themselves.

Custom plugins

Nearly every customer on the WordPress VIP platform uses one or more custom plugins. Like third-party plugins, they also need to be checked for compatibility. Asking the original developers to address the discovered issues is generally the best course of action.

Third-party or custom themes

While plugins are the most likely source of compatibility issues, don’t forget that third-party and custom themes also need to be compatible with PHP 8.0. The same approach of checking plugin code compatibility applies to theme code.

How to find PHP 8.0 compatibility issues

There are four main approaches development teams can use to review code to determine compatibility issues:

  1. Use PHP_CodeSniffer with the PHPCompatibility standard.
  2. Address known PHP Warnings that are PHP Fatal Errors under PHP 8.0.
  3. Create automated tests.
  4. Use PHPStan/Psalm or another static analysis tool.

Use PHP_CodeSniffer with the PHPCompatibility standard

PHP_CodeSniffer (PHPCS) tokenizes PHP files and detects violations of a defined set of coding standards. There are packages for the WordPress Coding Standards, and our own VIP Coding Standards (which we encourage customers to use).

There are also packages called PHPCompatibility and PHPCompatibilityWP, and these standards analyze a codebase for PHP cross-version compatibility. 

Because the results depend on tool capabilities and readiness, it is essential to use the develop branch of PHPCompatibility until version 10 is released. Version 10 will contain the sniffs related to PHP 8.0 (and PHP 8.1) compatibility. See our docs for instructions on how to set up your configuration to use the develop branch. Once version 10 is released, you can use that version instead.

The PHPCompatbilityWP package builds on top of the PHPCompatibility package but turns a few checks off for the backwards-compatibility items that WordPress core contains itself.

With PHPCS and PHPCompatibility/PHPCompatibilityWP set up, you can run a check:

phpcs --standard=PHPCompatibilityWP --severity=1 --runtime-set testVersion 8.0- --extensions=php <path-to-code>

The <path-to-code> could be a single custom or third-party plugin or theme if you wanted to start small, or the whole repository if you wanted to see all of the violations that need investigating and addressing.

The scanning steps will not detect every possible PHP version compatibility issue (such as incorrect runtime value types), but they will help identify the most common issues related to syntax.

Address known PHP Warnings that are PHP fatal errors under PHP 8.0

PHP 8.0 saw some reclassified engine warnings, where Warnings became fatal Error and TypeError Exceptions (and some Notices became Warnings). The PHP Warning texts to look for under PHP 7.4 are:

  • Attempt to assign property '*' of non-object
  • Attempt to modify property '*' of non-object
  • Attempt to increment/decrement property '*' of non-object
  • Creating default object from empty value
  • Cannot use a scalar value as an array
  • Cannot add element to the array as the next element is already occupied
  • Cannot unset offset in a non-array variable
  • Only arrays and Traversables can be unpacked
  • Invalid argument supplied for foreach()
  • Illegal offset type
  • Illegal offset type in isset or empty
  • Illegal offset type in unset
  • Cannot assign an empty string to a string offset
  • Division by zero
  • Use of undefined constant *

Fixing these Warnings is essential for the application to be compatible with PHP 8.0.

Note: There are other fatal errors under PHP 8.0 that were not even a Warning under PHP 7.4. Examples include:

  • Private methods may not be declared final except for the constructor.
  • Invalid signatures for magic methods.
  • Abstract trait method signature validation
  • Using parent:: with a parent class.
  • Incompatible overloaded method signatures (Liskov Substitution Principle)

Addressing these known changes is a good place to start. TypeError will be consistently thrown for all internal PHP functions, for instance when invalid parameter types are passed, even when strict type checking is not declared.

Also, note that the @ operator will no longer silence fatal errors under PHP 8.0.

Naturally, your application should ideally produce no errors, no warnings, and no notices. You are encouraged to address any you find. Some PHP Warnings under 8.x will be fatal errors under PHP 9.0, for example, potentially resulting in incorrect logic under PHP 8.x. Building in development time pre- and post-release to fix such issues and those that “escape discovery” during development is a best practice. It’s also an investment in site stability, and its ability to accurately meet the acceptance criteria for the associated feature.

Create automated tests

There are many different types of automated tests, but here we mean:

  •  Unit tests—mocks any WordPress-defined functions or classes, and doesn’t need an instance of a database to be available to run the tests.
  • Integration tests—loads WordPress and uses an actual test database

This topic is too big to cover well here, but there are a few things to consider:

  • The results depend on test suite completeness. If you don’t have many tests, then you’ll lack the necessary coverage to ensure compatibility.
  • Use strict assertions. For instance, using assertEquals() does a loose comparison, whereas assertSame() also checks the type as well.
  • Use strict code coverage. Add beStrictAboutCoversAnnotations=”true” and forceCoversAnnotations=”true” to the PHPUnit config file, and then use @covers annotations to find the accurate level of international code coverage across tests.
  • Test happy (behavior based on expected inputs) and unhappy (behavior based on unexpected inputs) paths to ensure that functions fail in an expected way, as this is where most strictness-related issues occur.
  • Run your tests on PHP 8.0. For the Integration (WordPress) tests, changes were made in 2021 to the WordPress core test suite that unlocked using the later versions of PHPUnit, which in turn supports PHP 8.0. This is supported by the WP Test Utils package, which includes PHPUnit Polyfills, Brain Monkey and Mockery support, additional function stubs for WordPress functions, and access to all WP native test utilities like the factory methods for content creation.
  • Consider writing tests before attempting a fix, to be more confident that the compatibility change has been successful.

Use PHPStan/Psalm or another static analysis tool

While PHPCS will catch some incompatibilities, there are some runtime changes that PHPCS isn’t designed to catch. One example that would be missed is native PHP functions being stricter with what types can be passed as parameters.

A tool like PHPStan, Psalm, or another static analysis tool can help here. But, to be most effective, they require your codebase to either use strict types (parameter and return types in the code), or be correctly documented (@param and @return lines in DocBlocks).

These tools typically have rule levels that allow fixing the lowest level issues first, and then gradually integrating the tool further to improve the quality of your codebase.

You can add knowledge for types for WordPress core code through extensions like phpstan-wordpress and psalm-plugin-wordpress.

Once configured, each run will highlight where you’re passing unexpected types into functions, which can cause fatal TypeError Exceptions to be thrown. Each of these will need to be fixed.

In many cases, you may be able to suppress a TypeError exception through the use of try-catch blocks or typecasting. However, we strongly recommend you don’t. Fixing the root cause will lead to stronger, less brittle and error-prone code, and will almost always pay off in the long run.

Get the latest content updates

Want to be notified about new content? Leave your email address below and we’ll make sure you stay updated.

How to get started with PHP 8.0 on WordPress VIP

Run the application locally

Running an instance of the application locally is a sensible first step in being able to detect and fix any compatibility issues. While you can use any local development environment, to ensure the best parity with the WordPress VIP platform, we recommend the VIP Local Development Environment. By running the command vip dev-env create --php=8.0 (with VIP-CLI 2.9.5 or later) and then completing the rest of the Setup Wizard, your application will run locally with PHP 8.0.

Check the VIP Code Analysis Bot on pull requests

If you look at any pull requests made to your repository under the wpcomvip organization, you’ll see the VIP Code Analysis Bot giving you feedback about PHPCS, PHP linting and SVG linting.

For the PHP Linting step, the bot will lint the PHP code with any version of PHP that is used for an application to which the repository deploys. If that version is PHP 7.4, it will now automatically lint using PHP 8.0 as well, in preparation for the upcoming switch. 

Enable PHP 8 on your WordPress VIP applications

Once you’ve done as much checking and fixing as you can locally, it’s time to enable PHP 8.0 on your WordPress VIP application. Start with your lowest environment, and check that everything looks good (including PHP logs via vip-cli or the Health Logs in the VIP Dashboard) before moving up to the production environment. 

You can enable PHP 8.0 on any environment via the new Software Management feature in VIP Dashboard. Check the Lobby announcement and documentation to learn more.

Leverage proactive help

Account teams for Premier customers are already reaching out to customers to discuss how we can support them. They’ll be sent the results from PHPCS and provided guidance on how to run these checks themselves. PHP Warnings that will become fatal errors will also be highlighted, giving them a headstart on addressing incompatibilities.

What about PHP 8.1?

The WordPress VIP platform also supports PHP 8.1. There are fewer changes between PHP 8.0 and PHP 8.1 than there are between PHP 7.4 and 8.0, which means that there should be fewer incompatibilities to address.

PHP 8.1:

  • Has active support from the PHP core developers until Nov 2023, and security support until Nov 2024.
  • Can handle more requests per second than PHP 8.0.
  • Has “beta compatibility” support on WordPress 5.9 and above – this means that there are some deprecation notices in preparation for PHP 9, but doesn’t affect the behavior of WordPress core.

The useful changes required for PHP 8.0, such as using strictly typed code and adding automated tests, will help with the PHP 8.1 rollout, as well as upgrades for WordPress 6.1, 6.2, 6.3 and beyond, as well as any feature releases you do. The QA process is often the bottleneck, so using some of the tools and approaches we’ve outlined can reduce manual labor and give you more confidence when deploying these changes.

If customers have questions about PHP 8.0, please open tickets with us.

CONTACT US

Request a WordPress VIP demo

Learn how we can help drive business growth for your organization.