Title: WordPress 5.9 and PHP 8.0-8.1
Author: Tonya Mork
Published: January 10, 2022

---

 [  ](https://profiles.wordpress.org/hellofromtonya/) [Tonya Mork](https://profiles.wordpress.org/hellofromtonya/)
4:15 pm _on_ January 10, 2022     
Tags: [5.9 ( 104 )](https://make.wordpress.org/core/tag/5-9/),
[dev-notes ( 648 )](https://make.wordpress.org/core/tag/dev-notes/)   

# WordPress 5.9 and PHP 8.0-8.1

PHPPHP The web scripting language in which WordPress is primarily architected. WordPress
requires PHP 7.4 or higher 8.1 was released on 25 November 2021. PHP 8.1 contains
new features, performance improvements, deprecations, and backward compatibility
breaks. For more information, see the [PHP 8.1 release page](https://www.php.net/releases/8.1/en.php),
[changelog](https://www.php.net/ChangeLog-8.php#PHP_8_1), and [migration guide](https://www.php.net/manual/en/migration81.php).

WordPress is not fully compatible with PHP 8.0 or 8.1. All remaining known PHP 8.1
issues are deprecation notices.

Please note, a deprecation notice is not an error, but rather an indicator of where
additional work is needed for compatibility before PHP 9 (i.e. when the notices 
become fatal errors). With a deprecation notice, the PHP code will continue to work
and nothing is broken.

The following is a breakdown of changes in WordPress CoreCore Core is the set of
software required to run WordPress. The Core Development Team builds WordPress. 
that pluginPlugin A plugin is a piece of software containing a group of functions
that can be added to a WordPress website. They can extend functionality or add new
features to your WordPress websites. WordPress plugins are written in the PHP programming
language and integrate seamlessly with WordPress. These can be free in the WordPress.
org Plugin Directory [https://wordpress.org/plugins/](https://wordpress.org/plugins/)
or can be cost-based plugin from a third-party. and theme developers need to be 
aware of and accommodate in their code.

## PHP 8.1 Remaining known deprecation notices

Deprecation notices remain in WordPress 5.9 and work will continue in the 6.0 cycle.

What is required to resolve each?

 * Resolution requires a more structural and all-encompassing solution for input
   validation (i.e. validating the data type and, in some cases, value passed to
   a function/method) to be architected and implemented to properly fix the underlying
   bugbug A bug is an error or unexpected result. Performance improvements, code
   optimization, and are considered enhancements, not defects. After feature freeze,
   only bugs are dealt with, with regressions (adverse changes from the previous
   version) being the highest priority. rather than introducing buggy unexpected
   behavior by haphazardly silencing the deprecation notice.
 * Each notice needs investigation to determine the impact of such changes.
 * Each change requires thorough testing including full coverage happy and unhappy
   unit/integration tests.

The remaining known deprecation notices include:

 * Functions in the `wp-includes/formatting.php` file.
 * `parse_url()` or `wp_parse_url()` passed directly to a non-nullable in PHP native
   function without validating a `string` type is returned (i.e. both will return`
   null` when the requested component doesn’t exist within the given URLURL A specific
   web address of a website or web page on the Internet, such as a website’s URL
   www.wordpress.org ([see the PHP manual](https://www.php.net/manual/en/function.parse-url.php#refsect1-function.parse-url-returnvalues))).
 * `wp_xmlrpc_server::mw_newPost()`: changing content structure default values from`
   null` to an empty string. This change requires a review from XMLRPC domain expert
   and more testing.
 * Upgrade to Requests 2.0.0: Originally planned for WordPress 5.9, but reverted
   due to issues with WordPress Core’s updater. Currently planned for 6.0 (TracTrac
   An open source project by Edgewall Software that serves as a bug tracker and 
   project management tool for WordPress. [#54504](https://core.trac.wordpress.org/ticket/54504)).

To follow or contribute to this ongoing work, see Trac [#53465](https://core.trac.wordpress.org/ticket/53465),
[#53635](https://core.trac.wordpress.org/ticket/53635), [#54183](https://core.trac.wordpress.org/ticket/54183),
and [#54730](https://core.trac.wordpress.org/ticket/54730).

## WordPress Core Changes

### PHP 8.0 polyfills introduced

The following PHP 8 polyfills are available in WordPress 5.9:

 * [`array_key_first()`](https://www.php.net/manual/en/function.array-key-first.php):
   gets the first key an array.
 * [`array_key_last()`](https://www.php.net/manual/en/function.array-key-last.php):
   gets the last key of an array.
 * [`str_contains()`](https://www.php.net/manual/en/function.str-contains.php): 
   determines if the string contains a given substring.
 * [`str_starts_with()`](https://www.php.net/manual/en/function.str-starts-with.php):
   checks if a string starts with a given substring.
 * [`str_ends_with()`](https://www.php.net/manual/en/function.str-ends-with.php):
   checks if a string ends with a given substring.

Each polyfill loads into memory when the site is run on PHP versions less than PHP
8.0.

### PHP 8.0 named parameters: match parent to child class method signatures

As [noted last year in the PHP 8.0 dev note](https://make.wordpress.org/core/2020/11/23/wordpress-and-php-8-0/),
WordPress Core is not compatible nor supports named parameters:

> Using named parameters when calling WordPress functions and class methods is explicitly
> not supported and highly discouraged until this audit can be completed, as during
> the audit, parameter names are subject to change without notice. When this audit
> has been completed, it will be announced in a future developer note.

In 5.9, WordPress Core’s parent and child class method signatures were changed. 
The parameter names match in the parent and child methods.

If you extend Core classes and choose to support named parameters, you’ll need to
audit and change each method being overloaded to ensure the method signatures match
the Core class being extended.

To follow or contribute to this review, see Trac [#51553](https://core.trac.wordpress.org/ticket/51553),
and [#50531](https://core.trac.wordpress.org/ticket/50531).

### PHP 8.1 `readonly()` renamed to `wp_readonly()`

Though originally planned as a reserved keyword, PHP 8.1 changed `readonly` keyword
to a (limited) contextual keyword with potential future plans to deprecate.

WordPress 5.9 renames the `readonly()` function to `wp_readonly()`. For PHP 8.0 
or earlier, the original `readonly()` function is loaded into memory but deprecated.

Reference:

 * [PHP RFC : Readonly properties 2.0](https://wiki.php.net/rfc/readonly_properties_v2)
 * [PHP commit that implements the readonly properties](https://github.com/php/php-src/commit/6780aaa5)
 * [PHP PR that allows readonly as a function name](https://github.com/php/php-src/pull/7468)

### PHP 8.1 return type enforcement and new `#[ReturnTypeWillChange]` attribute

PHP 8.1 introduces a new `#[ReturnTypeWillChange]` attribute to silence the deprecation
notice for each PHP native interface method where the overloaded method’s return
type is incompatible. WordPress Core adds the attribute to each of its instances.

When overloading a PHP native interface method, you should either have the return
type declared (in a covariant compatible manner with the PHP native interface method
declaration), or add the `#[ReturnTypeWillChange]` attribute to silence the deprecation
notice.

For example, when implementing the [`ArrayAccess` interface](https://www.php.net/manual/en/class.arrayaccess.php),
ensure the required methods are compatible or add the attribute as follows:

    ```wp-block-code
    /**
     * @param mixed $offset The offset to check for.
     *
     * @return bool True on success or false on failure.
     */
    #[ReturnTypeWillChange]
    public function offsetExists( $offset ) {
    	// the code
    }

    /**
     * @param mixed $offset The offset to retrieve.
     *
     * @return mixed The offset’s value.
     */
    #[ReturnTypeWillChange]
    public function offsetGet( $offset ) {
    	// the code
    }

    /**
     * @param mixed $offset The offset to assign the value to.
     * @param mixed $value  The value to set.
     */
    #[ReturnTypeWillChange]
    public function offsetSet( $offset, $value ) {
    	// the code
    }

    /**
     * @param mixed $offset The offset to unset.
     */
    #[ReturnTypeWillChange]
    public function offsetUnset( $offset ) {
    	// the code
    }
    ```

See the [PHP RFC: Add return type declarations for internal methods](https://wiki.php.net/rfc/internal_method_return_types).

### PHP 8.1 MySQLi default error mode changed

PHP 8.1 changed the default mysqli error mode from silent to fatal error.

Prior to PHP 8.1, the default error handling mode of MySQLi was silent (i.e. `MYSQLI_REPORT_OFF`).
An error in the extension, database, query, or the database connection returned `
false` and emitted a PHP warning.

PHP 8.1 changed the default error mode to `MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT`.
An error in the extension, database, query, or the database connection throws a 
fatal error exception.

WordPress Core has its own error reporting and gracefully handles the database errors
by inspecting the error codes. In 5.9, Core sets MySQLi error reporting to off to
avoid fatal errors due to uncaught exceptions and maintains the current behavior(
see Trac [#52825](https://core.trac.wordpress.org/ticket/52825)).

If you are using `wpdb`, 5.9 takes care of this for you. However, if you are not
using `wpdb`, you will need to make changes in your theme or plugins. It is recommended
to switch to `wpdb`.

References:

 * [PHP 8.1: MySQLi: Default error mode set to exceptions](https://php.watch/versions/8.1/mysqli-error-mode)
 * [PHP RFC: Change Default mysqli Error Mode](https://wiki.php.net/rfc/mysqli_default_errmode)

### PHP 8.1 deprecation: passing null to non-nullable PHP native functions parameters

A deprecation notice is thrown when passing a `null` value to a PHP native function’s
parameter that is not declared nullable. The value will continue to be coerced, 
meaning the PHP behavior has not (yet) changed. However, in PHP 9, a `TypeError`
will be thrown.

For example, passing `null` to `strlen()` (which expects a `string` type) will throw
the following notice:

    ```wp-block-code
    Deprecated: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in .. on line ..
    ```

The deprecation notice identifies where an underlying bug exists in the code base.
Rather than merely silencing the deprecation, the approach taken in WordPress Core
is to fix each underlying bug notice through input validation (i.e. validating what
is passed to the function) or targeted guarding to skip processing for type mismatches.

[As noted previously](http://php-8-1-remaining-known-deprecation-notices), deprecation
notices remain in WordPress Core. These remaining deprecation notices will require
a more structural and all-encompassing architectural solution and tests to avoid
haphazardly silencing the deprecation notice while potentially introducing buggy,
unexpected behavior.

To follow or contribute to this effort, see Trac [#54730](https://core.trac.wordpress.org/ticket/54730).

#### What do you need to do?

Analyze each deprecation notice in your theme or plugin and craft a solution that
resolves the bug.

For example, skip the `trim()` operation when the value to trimmed is not scalar:

    ```wp-block-code
    if ( is_scalar( $value ) ) {
    	$value = trim( $value );
    }
    ```

Check that a `string` type is returned from the following function before passing
the returned value to a PHP native function:

 * `parse_url()` or `wp_parse_url()` will return `null` when the requested component
   doesn’t exist within the given URL ([see the PHP manual](https://www.php.net/manual/en/function.parse-url.php#refsect1-function.parse-url-returnvalues)).
 * `filter_input()` will return `null` if the `var_name` to get is not set or if
   using `FILTER_NULL_ON_FAILURE` flag but the filterFilter Filters are one of the
   two types of Hooks [https://codex.wordpress.org/Plugin_API/Hooks](https://codex.wordpress.org/Plugin_API/Hooks).
   They provide a way for functions to modify data of other functions. They are 
   the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated
   manner, and should never have side effects such as affecting global variables
   and output. fails.

For example:

    ```wp-block-code
    $url_path     = parse_url( $url, PHP_URL_PATH );
    $url_filename = '';
    if ( is_string( $url_path ) && '' !== $url_path ) {
    	$url_filename = basename( $url_path );
    }
    ```

References:

 * [PHP RFC: Deprecate passing null to non-nullable arguments of internal functions](https://wiki.php.net/rfc/deprecate_null_to_scalar_internal_arg)
 * [PHP.Watch: PHP 8.1: Passing `null` to non-nullable internal function parameters is deprecated](https://php.watch/versions/8.1/internal-func-non-nullable-null-deprecation)

### PHP 8.1 deprecation: autovivification on false

[Autovivification](https://en.wikipedia.org/wiki/Autovivification) is the automatic
creation of an array. When a variable is defined as a boolean `false` and then used
as an array as shown,

    ```wp-block-code
    $arr   = false;
    $arr[] = 2;
    ```

PHP 8.1 throws a deprecation notice:

    ```wp-block-code
    Deprecated: Automatic conversion of false to array is deprecated in .. on line ..
    ```

In PHP 8.1, this code will continue to work; however, in PHP 9.0, it will result
in a fatal error.

There are multiple ways to fix your code to not only resolve the deprecation notice
but to also avoid a fatal error in the future when PHP 9 is released. Some of ways
include:

 * Declare an array before using it, i.e. `$arr = array();`.
 * Check the returned value to ensure it is an array or at minimum not false before
   using.
 * When getting an option with `get_option()`, if an `array` type is expected, set
   the default to an empty array.

    ```wp-block-code
    $options = get_option( ‘some_option’, array() );
    ```

For more information, see the [PHP RFC: Deprecate autovivification on false](https://wiki.php.net/rfc/autovivification_false).

### PHP 8.1 deprecation: implicit incompatible float to int conversion

The implicit conversion of float to int which leads to precision loss will throw
a deprecation notice.

    ```wp-block-code
    $arr = array();
    $arr[15.5]; // will throw the deprecation notice because 0.5 is lost
    ```

References:

 * PHP Manual: [Implicit incompatible float to int conversions](https://www.php.net/manual/en/migration81.deprecated.php#migration81.deprecated.core.implicit-float-conversion)
 * PHP.Watch: [PHP 8.1: Implicit incompatible float to in conversion is deprecated](https://php.watch/versions/8.1/deprecate-implicit-conversion-incompatible-float-string)

## PHP 8.1 other notable deprecations and changes

The following functions are deprecated:

 * Date functions: `date_sunrise()`, `date_sunset()`, `gmstrftime()`, `strftime()`,`
   strptime()`.
 * Hash functions:  `mhash()`, `mhash_keygen_s2k()`, `mhash_count()`, `mhash_get_block_size()`,
   and `mhash_get_hash_name()` .
 * Calling `key()`, `current()`, `next()`, `prev()`, `reset()`, or `end()` on objects
   is deprecated.

The following functions changed:

 * The default of `ENT_COMPAT` changed to `ENT_QUOTES | ENT_SUBSTITUTE` in these
   functions `htmlspecialchars()`, `htmlentities()`, `htmlspecialchars_decode()`,`
   html_entity_decode()`, and `get_html_translation_table()` (Trac [#53465](https://core.trac.wordpress.org/ticket/53465)).
 * Undocumented operation abbreviations can no longer be passed to `version_compare()`.

See the [Migrating from PHP 8.0.x to PHP 8.1.x](https://www.php.net/manual/en/migration81.php)
for a complete list of deprecations and changes.

## External Libraries

WordPress 5.9 includes the following updated external libraries:

 * GetID3 1.9.21 which includes preliminary PHP 8.1 support (Trac [#54162](https://core.trac.wordpress.org/ticket/54162)).
 * SimplePie 1.5.7 which includes significant PHP 8.0 and 8.1 compatibility improvements(
   Trac [#54659](https://core.trac.wordpress.org/ticket/54659)).
 * PHPMailer 6.5.1 which includes preliminary PHP 8.1 support (Trac [#53953](https://core.trac.wordpress.org/ticket/53953)).

The Requests 2.0.0 library was originally planned for WordPress 5.9. However, due
to issues with WordPress Core’s upgrader, it was reverted and planned for 6.0 (Trac
[#54504](https://core.trac.wordpress.org/ticket/54504)).

## Test Suites and Tooling

### Changes to the WordPress Core PHP Test Suite

> [Changes to the WordPress Core PHP Test Suite](https://make.wordpress.org/core/2021/09/27/changes-to-the-wordpress-core-php-test-suite/)

### What about static tooling? Can it identify incompatibilities?

PHPCompatibility can only find a limited amount of these issues. PHPStan/Psalm/Exakat
may find more, but are prone to false positives for non-typed code bases.

### A Good Test Suite is the first line of defense

Most of the incompatibilities can be found through a good test suite, which includes
full test coverage of both happy and unhappy paths.

Theme and plugin developers are encouraged to extend your test suites.

WordPress Core’s test coverage is currently less than 10%. You are invited and encouraged
to contribute tests to grow test coverage in WordPress.

### PHPUnit deprecation notices

In PHPUnit < 9.5.10/8.5.21, if a PHP native deprecation notice was encountered, 
PHPUnit would:

 1. Show a test which causes a deprecation notice to be thrown as **“errored”**;
 2. Show **the first** deprecation notice it encountered;
 3. Exit with a **non-0 exit code (2)**, which will **fail** a CI build.

As of PHPUnit 9.5.10/8.5.21, if a PHP native deprecation notice is encountered, 
PHPUnit will:

 1. Show a test which causes a PHP deprecation notice to be thrown as **“risky”**;
 2. Show **all** deprecation notices it encountered;
 3. Exit with a **0 exit code**, which will **pass** a CI build.

To follow or contribute to this review, see Trac [#54183](https://core.trac.wordpress.org/ticket/54183).

#### Why is this a problem?

These deprecations will become errors in the next PHP major and they will still 
need to be fixed. As CI builds pass, the deprecations go unnoticed. This means more
deprecations remaining in WordPress Core, and would lead to more reports of deprecation
notices from end-users.

#### What’s changing in WordPress Core?

The single site and multisitemultisite Used to describe a WordPress installation
with a network of multiple blogs, grouped by sites. This installation type has shared
users tables, and creates separate database tables for each blog (wp_posts becomes
wp_0_posts). See also **network**, **blog**, **site** PHPUnit configuration files
for WordPress Core now include the following attributes:

    ```wp-block-code
    convertErrorsToExceptions="true"
    convertWarningsToExceptions="true"
    convertNoticesToExceptions="true"
    convertDeprecationsToExceptions="true"
    ```

#### How does this solve the problem?

This will cause CI builds to fail when a native PHP deprecation notice is encountered,
meaning that deprecation notices can not go unnoticed.

#### Are there any negatives?

Only the first deprecation notice will be shown for a test, and there may be more
issues hiding behind a deprecation.

## What’s coming in PHP 8.2

A significant change is coming in PHP 8.2 which could impact your themes and plugins.
The  [RFC to deprecate dynamic properties](https://wiki.php.net/rfc/deprecate_dynamic_properties)
was approved. See the RFC for more information.

---

_Props to [@costdev](https://profiles.wordpress.org/costdev/) and [@jrf](https://profiles.wordpress.org/jrf/)
for contributing to this dev notedev note Each important change in WordPress Core
is documented in a developers note, (usually called dev note). Good dev notes generally
include a description of the change, the decision that led to this change, and a
description of how developers are supposed to work with that change. Dev notes are
published on Make/Core blog during the beta phase of WordPress release cycle. Publishing
dev notes is particularly important when plugin/theme authors and WordPress developers
need to be aware of those changes.In general, all dev notes are compiled into a 
Field Guide at the beginning of the release candidate phase., and to [@costdev](https://profiles.wordpress.org/costdev/),
[@antonvlasenko](https://profiles.wordpress.org/antonvlasenko/), [@javiercasares](https://profiles.wordpress.org/javiercasares/),
and [@andraganescu](https://profiles.wordpress.org/andraganescu/) for reviewing_.

[#5-9](https://make.wordpress.org/core/tag/5-9/), [#dev-notes](https://make.wordpress.org/core/tag/dev-notes/)

### Share this:

 * [  Threads ](https://make.wordpress.org/core/2022/01/10/wordpress-5-9-and-php-8-0-8-1/?share=threads)
 * [  Mastodon ](https://make.wordpress.org/core/2022/01/10/wordpress-5-9-and-php-8-0-8-1/?share=mastodon)
 * [  Bluesky ](https://make.wordpress.org/core/2022/01/10/wordpress-5-9-and-php-8-0-8-1/?share=bluesky)
 * [  X ](https://make.wordpress.org/core/2022/01/10/wordpress-5-9-and-php-8-0-8-1/?share=x)
 * [  Facebook ](https://make.wordpress.org/core/2022/01/10/wordpress-5-9-and-php-8-0-8-1/?share=facebook)
 * [  LinkedIn ](https://make.wordpress.org/core/2022/01/10/wordpress-5-9-and-php-8-0-8-1/?share=linkedin)

 1.  ![](https://secure.gravatar.com/avatar/8ba399b138bbff0b84cc08dd7f802dbce6f2ce4c5f26157ef5e2c6a8d2dabf1e?
     s=32&d=mm&r=g)
 2.   [kitchin](https://profiles.wordpress.org/kitchin/)  9:40 pm _on_ January 22, 
     2022
 3.  Second paragraph
 4.  > WordPress is not fully compatible
 5.  should be
 6.  > WordPress is now fully compatible
 7.   * ![](https://secure.gravatar.com/avatar/700febabf646717b35cab3a3bbc42e405237922fccda8b01ad07cde219de62bd?
        s=32&d=mm&r=g)
      *  [Tonya Mork](https://profiles.wordpress.org/hellofromtonya/)  10:16 pm _on_
        January 24, 2022
      * Actually, it is correct. WordPress 5.9 is not fully capable with PHPPHP The
        web scripting language in which WordPress is primarily architected. WordPress
        requires PHP 7.4 or higher 8.0 or 8.1. Compatibility work is ongoing.
         - ![](https://secure.gravatar.com/avatar/ed3efed01cf34a98db5d7a536b4eb95913ea42c83de6543f82c99ee8d873efe1?
           s=32&d=mm&r=g)
         -  [Cristescu Bogdan](https://profiles.wordpress.org/cbogdan/)  7:49 pm _on_
           February 4, 2022
         - You funny people! We should apreciate the holly report! Because it is eaven
           a veeeeeery educative one… or at least THE EFFORT …has more than more caps
           lock!
         - ![](https://secure.gravatar.com/avatar/0bdb579a78fd256deb031f2d23258ff8bbe7b72fe1baf8cd9f5e00a04d0efd12?
           s=32&d=mm&r=g)
         -  [Netdoctor](https://profiles.wordpress.org/browntrout/)  5:43 am _on_ February
           9, 2022
         - [@hellofromtonya](https://profiles.wordpress.org/hellofromtonya/) – Maybe
           the following two pages should be updated to clarify current PHPPHP The 
           web scripting language in which WordPress is primarily architected. WordPress
           requires PHP 7.4 or higher version status?
            [Server Environment – Make WordPress Hosting](https://make.wordpress.org/hosting/handbook/server-environment/#php)
           and [https://wordpress.org/about/requirements/](https://wordpress.org/about/requirements/)
         - ![](https://secure.gravatar.com/avatar/ec624e13189ca340d35d7c6b0cd36305e4f47f62baffc6ba0f9fd9b60aa3dc63?
           s=32&d=mm&r=g)
         -  [pebro](https://profiles.wordpress.org/pebro/)  2:22 pm _on_ February 20,
           2022
         - I agree. Even some plugins do not work properly on php 8+
 8.  ![](https://secure.gravatar.com/avatar/3c8800cc963939d2f08c00c93f16aefd6f96991b0295f2ab658f58b45e428fd8?
     s=32&d=mm&r=g)
 9.   [Austin Passy](https://profiles.wordpress.org/austyfrosty/)  12:21 am _on_ February
     3, 2022
 10. Really looking forward to PHPPHP The web scripting language in which WordPress
     is primarily architected. WordPress requires PHP 7.4 or higher >= 8.0 support.
 11. ![](https://secure.gravatar.com/avatar/78aee0cb87b51effdfcf61b9a60a99315b5550d06e820f7d4b99c0d81cfafe13?
     s=32&d=mm&r=g)
 12.  [stlecho](https://profiles.wordpress.org/stlecho/)  1:43 pm _on_ April 9, 2022
 13. Any updates concerning PHPPHP The web scripting language in which WordPress is
     primarily architected. WordPress requires PHP 7.4 or higher >= 8.0 support ?

Comments are closed.

# Post navigation

[← Updates for Settings, Styles, and theme.json](https://make.wordpress.org/core/2022/01/08/updates-for-settings-styles-and-theme-json/)

[Performance Chat Agenda: 11 January 2022 →](https://make.wordpress.org/core/2022/01/10/performance-chat-agenda-11-january-2022/)