WordPress and PHP 8.3: what changes for plugins and themes
Short answer
WordPress 6.4 and later work with PHP 8.3; your plugins and theme decide whether your site does. Of the PHP 8.3 changes you’re most likely to meet in plugins and themes, most only log deprecation notices, and the code keeps working. What can stop code depends on values while the site runs, for example an invalid date given to DateTime::modify(), which no code check can see in advance. php.net lists the full set of changes. PHP 8.3 gets security fixes until 31 December 2027.
Is WordPress ready for PHP 8.3?
PHP 8.3.0 was released on 23 November 2023. Its active support ended on 31 December 2025; it gets security fixes until 31 December 2027 (php.net).
The WordPress core team’s compatibility page lists WordPress 6.4 and later as compatible with PHP 8.3. That covers WordPress itself; the changes below concern the code of your plugins and theme.
The short version
The PHP 8.3 changes you’re most likely to meet in plugins and themes. php.net lists the full set of backward incompatible changes and deprecated features.
| What changes in PHP 8.3 | What happens | Kind |
|---|---|---|
DateTime::modify() with a date it can’t read | An exception instead of a warning: the page stops unless the code catches it | Depends on values |
| A negative index in an empty array | The next index continues from it instead of starting at 0 | Silent change |
get_class() without arguments, assert_options(), ASSERT_* and MT_RAND_PHP constants, changed return types of built-in methods | Deprecation notice, code keeps working | Notices |
++ on an empty or non-alphanumeric string | Deprecation notice, depends on values | Notices |
What can stop the code: only with some values
Of the PHP 8.3 changes you’re most likely to meet in plugins and themes, none stops code in every case. One can, depending on the values it gets. php.net’s changelog for DateTime::modify(): “DateTime::modify() now throws DateMalformedStringException if an invalid string is passed. Previously, it returned false, and a warning was emitted.” (php.net)
So a date a visitor typed, or a setting left in an odd format, used to give a warning and let the plugin carry on; on PHP 8.3 it stops the page unless the plugin catches the exception:
wp-content/plugins/event-calendar/includes/reminders.php
<?php
$reminder = new DateTime('2026-05-01');
$result = $reminder->modify('next thursday-ish'); // a date a visitor typed
echo $result ? $result->format('j F Y') : 'Not a valid date', "\n";
Warning: DateTime::modify(): Failed to parse time string (next thursday-ish) at position 13 (-): Unexpected character in /var/www/html/wp-content/plugins/event-calendar/includes/reminders.php on line 3
Not a valid dateFatal error: Uncaught DateMalformedStringException: DateTime::modify(): Failed to parse time string (next thursday-ish) at position 13 (-): Unexpected character in /var/www/html/wp-content/plugins/event-calendar/includes/reminders.php:3
Stack trace:
#0 /var/www/html/wp-content/plugins/event-calendar/includes/reminders.php(3): DateTime->modify('next thursday-i...')
#1 {main}
thrown in /var/www/html/wp-content/plugins/event-calendar/includes/reminders.php on line 3wp-content/plugins/event-calendar/includes/reminders.phpCode: catching the exception
Code that catches the exception handles both versions; PHP 8.2 still writes its warning:<?php
$reminder = new DateTime('2026-05-01');
try {
$result = $reminder->modify('next thursday-ish'); // a date a visitor typed
} catch (Exception $e) { // PHP 8.3 and later throw here
$result = false;
}
echo $result ? $result->format('j F Y') : 'Not a valid date', "\n";
Warning: DateTime::modify(): Failed to parse time string (next thursday-ish) at position 13 (-): Unexpected character in /var/www/html/wp-content/plugins/event-calendar/includes/reminders.php on line 4
Not a valid dateNot a valid date
No code check can tell in advance which dates a site will pass, so watch your error log after switching.
A silent change: negative array indexes
“Assigning a negative index $n to an empty array will now make sure that the next index is $n+1 instead of 0.” (php.net) No notice, no error; only the keys change:
wp-content/plugins/member-list/includes/ranking.php
<?php
$ranking = [];
$ranking[-3] = 'Guest';
$ranking[] = 'Adam';
$ranking[] = 'Sara';
echo implode(', ', array_keys($ranking)), "\n";
-3, 0, 1-3, -2, -1Code that relies on the old numbering (for example, looking for the first item at index 0) gets a different result without any message.
What only shows notices: the deprecations you’re most likely to meet
A deprecation notice means: this still works, but a future PHP version is expected to change it. The page is built as usual. PHP 8.3 deprecates more than these; php.net lists the full set in its deprecated features in PHP 8.3.
get_class() without arguments
“Calling get_class() and get_parent_class() without arguments is now deprecated.” (php.net) The fix, with tested code, is in PHP 8.2 reaches end of life: self::class inside the class.
assert_options() and the ASSERT_* constants
“The assert_options() function is now deprecated. The ASSERT_ACTIVE, ASSERT_BAIL, ASSERT_CALLBACK, ASSERT_EXCEPTION, and ASSERT_WARNING constants have been deprecated.” (php.net) A line using both gets two notices; PHP 8.5 words them differently:
wp-content/plugins/dev-checks/dev-checks.php
<?php
if (assert_options(ASSERT_ACTIVE)) {
echo "Assertions are on\n";
}
Assertions are onDeprecated: Constant ASSERT_ACTIVE is deprecated in /var/www/html/wp-content/plugins/dev-checks/dev-checks.php on line 2
Deprecated: Function assert_options() is deprecated in /var/www/html/wp-content/plugins/dev-checks/dev-checks.php on line 2
Assertions are onDeprecated: Constant ASSERT_ACTIVE is deprecated since 8.3, as assert_options() is deprecated in /var/www/html/wp-content/plugins/dev-checks/dev-checks.php on line 2
Deprecated: Function assert_options() is deprecated since 8.3 in /var/www/html/wp-content/plugins/dev-checks/dev-checks.php on line 2
Assertions are onThis is how a check reports it:
wp-content/plugins/dev-checks/dev-checks.phpCode: reading the setting with ini_get()
<?php
if (ini_get('assert.active')) {
echo "Assertions are on\n";
}
Assertions are onAssertions are on
MT_RAND_PHP
“The MT_RAND_PHP Mt19937 variant is deprecated.” (php.net) Worth knowing before fixing it: the default variant gives a different sequence of numbers for the same seed, so a plugin that relied on a fixed “random” order shows a different one.
wp-content/plugins/daily-quote/daily-quote.php wp-content/plugins/daily-quote/daily-quote.phpCode: before and after (note the different number)
<?php
mt_srand(42, MT_RAND_PHP); // the same "random" quote for everyone today
echo 'Quote number ', mt_rand(1, 100), "\n";
Quote number 64Deprecated: Constant MT_RAND_PHP is deprecated in /var/www/html/wp-content/plugins/daily-quote/daily-quote.php on line 2
Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in /var/www/html/wp-content/plugins/daily-quote/daily-quote.php on line 2
Quote number 64Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in /var/www/html/wp-content/plugins/daily-quote/daily-quote.php on line 2
Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in /var/www/html/wp-content/plugins/daily-quote/daily-quote.php on line 2
Quote number 64<?php
mt_srand(42); // the same "random" quote for everyone today
echo 'Quote number ', mt_rand(1, 100), "\n";
Quote number 43Quote number 43
Changed return types of built-in methods
A plugin class that extends a PHP class and overrides one of its methods must promise a compatible return type. PHP 8.3 narrowed some, for example ArrayObject::asort(), which now returns true; an override that still promises bool gets a notice:
wp-content/plugins/member-list/includes/class-sorted-list.php wp-content/plugins/member-list/includes/class-sorted-list.phpCode: before and after
<?php
class Sorted_List extends ArrayObject {
public function asort(int $flags = SORT_REGULAR): bool {
return parent::asort($flags);
}
}
$list = new Sorted_List(['b' => 'Sara', 'a' => 'Adam']);
$list->asort();
echo implode(', ', (array) $list), "\n";
Adam, SaraDeprecated: Return type of Sorted_List::asort(int $flags = SORT_REGULAR): bool should either be compatible with ArrayObject::asort(int $flags = SORT_REGULAR): true, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/html/wp-content/plugins/member-list/includes/class-sorted-list.php on line 3
Adam, Saratrue, like the method it overrides; it runs without a notice on PHP 8.2, 8.3 and 8.5:<?php
class Sorted_List extends ArrayObject {
public function asort(int $flags = SORT_REGULAR): true {
return parent::asort($flags);
}
}
$list = new Sorted_List(['b' => 'Sara', 'a' => 'Adam']);
$list->asort();
echo implode(', ', (array) $list), "\n";
Adam, SaraAdam, SaraAdam, Sara
++ on empty or non-alphanumeric strings
“Using the increment operator (++) on empty, non-numeric, or non-alphanumeric strings is now deprecated.” (php.net) Whether it happens depends on the string’s value at run time; PHP 8.5 words the message differently:
wp-content/plugins/member-list/includes/codes.phpCode: incrementing an empty string
<?php
$code = ''; // no code saved yet
$code++;
var_dump($code);
string(1) "1"Deprecated: Increment on non-alphanumeric string is deprecated in /var/www/html/wp-content/plugins/member-list/includes/codes.php on line 3
string(1) "1"Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in /var/www/html/wp-content/plugins/member-list/includes/codes.php on line 3
string(1) "1"
How to check your site before switching
- Find your current PHP version: Tools → Site Health → Info → Server.
- Check your plugins and theme for PHP 8.3. With CompatNav, choose PHP 8.3 next to Check readiness for and start a scan. It finds the deprecated functions, constants and return types above; the date and array changes depend on values and don’t show up in any code check.
- Fix what will break before you switch; notices can wait for the plugins’ next updates.
- Switch, then watch your important pages and your error log for a few days.
A newer version gives you more time before the next upgrade: WordPress and PHP 8.4 and WordPress and PHP 8.5 list what changes there.
Key takeaways
- PHP 8.3 was released on 23 November 2023; its active support ended on 31 December 2025, and it gets security fixes until 31 December 2027 (php.net). WordPress 6.4 and later are compatible with it.
- Of the changes you’re most likely to meet in plugins and themes, most only add deprecation notices:
get_class()without arguments,assert_options(),MT_RAND_PHP, changed return types of built-in methods. - What can stop code depends on values: an invalid date string now throws an exception in
DateTime::modify()instead of a warning. - One change is silent: after a negative index in an empty array, the next index continues from it instead of starting at 0.
- Check your plugins and theme before switching, and watch the error log after: no code check sees problems that depend on values.
Frequently asked questions
Is PHP 8.3 still supported?
Yes, with security fixes only: its active support ended on 31 December 2025, and security fixes continue until 31 December 2027 (php.net). PHP 8.4 and 8.5 are supported for longer.
PHP 8.3 or a newer version?
If your plugins and theme are ready for a newer version and your host offers it, the newer one gives you more time: PHP 8.4 gets security fixes until 31 December 2028, PHP 8.5 until 31 December 2029. PHP 8.3 is the smaller step from 8.1 or 8.2.
Is WordPress compatible with PHP 8.3?
Yes. The WordPress core team’s compatibility page lists WordPress 6.4 and later as compatible with PHP 8.3. Your plugins and theme are a separate question.
Check your own site before you upgrade
CompatNav is a free WordPress plugin. It reads the code of your plugins and themes on your own server and tells you, in plain words, what will break and what will only show notices on the PHP version you choose. It never changes your code. It can’t see problems that only appear while code runs with real data, so a quick check of your site after the upgrade still matters.
Sources
- php.net: Supported Versions
- php.net: Backward Incompatible Changes in PHP 8.3.x
- php.net: Deprecated features in PHP 8.3.x
- php.net: DateTime::modify() (changelog)
- make.wordpress.org: PHP Compatibility and WordPress Versions
About the code examples: each output is the real output of the code shown, run with the official PHP builds, without a php.ini, with all errors reported and displayed. Only the file path was replaced by a neutral server path.