Ensure your WordPress plugins are fully compatible with PHP 8! This guide covers common issues, solutions, and optimizations to make the most of PHP 8’s performance improvements.
Your host flips a server to PHP 8. A plugin that ran clean yesterday throws a fatal error today. Nobody touched the code. The language changed underneath it.
That is the whole story of PHP 8 compatibility. PHP 8 is faster, and it is stricter, and the strictness is what breaks old plugins. Things earlier versions quietly let slide now stop the request cold. If you build for WordPress, you will meet these edges eventually, usually on someone else’s server, usually at a bad time.
Here is the short version of what tends to break, and how we fix it, so you can update your plugin on your schedule instead of a support ticket’s.
Table of Contents
- Overview of PHP 8 Changes
- Common Compatibility Issues in PHP 8
- Resolving Compatibility Issues
- Optimizing Plugins for PHP 8
- Testing and Debugging Plugins on PHP 8
- Conclusion
Overview of PHP 8 Changes
PHP 8 is not a small bump. It is a real jump in the language. A few changes matter most for WordPress work:
- Just-In-Time (JIT) Compilation: PHP 8 can compile hot code paths to machine code at runtime. It helps genuinely CPU-bound work. Be honest with yourself about whether your plugin has any: most WordPress code is waiting on the database and the network, not the CPU, so JIT rarely moves the needle here.
- New Syntax Features: The nullsafe operator (
?->), named arguments, and union types make code shorter and clearer. They also raise your minimum PHP version the moment you use them. - Stricter Error Handling: This is the one that bites. PHP 8 turned a pile of quiet warnings into thrown errors. Passing the wrong type to a built-in function, or the wrong number of arguments, now throws a
TypeErrororArgumentCountErrorinstead of shrugging and continuing.
Speed is the reward. The stricter rules are the cost, and they land hardest on plugins written for PHP 5 or PHP 7, where a lot of loose behavior used to be fine.
Common Compatibility Issues in PHP 8
Four issues cover most of what you will actually run into.
1. Deprecated Functions
Some functions are simply gone. create_function() and each() were removed in PHP 8.0, not just deprecated. Call one and you get a fatal error, not a warning. If your plugin still leans on either, it will not load.
2. Stricter Type Handling
PHP 8 is far pickier about types. Implicit conversions that earlier versions accepted can now throw a TypeError. That shows up wherever you hand user input or third-party data straight into a function that expects a specific type.
3. Changes to Comparison Operators
PHP 8 changed how numbers compare against non-numeric strings. It no longer quietly turns the string into 0. In PHP 7, 0 == 'foo' was true. In PHP 8 it is false. Any plugin that relied on that old behavior in a loose comparison can now branch the wrong way without warning.
4. Nullsafe Operator
The nullsafe operator (?->) shortens null checks in chained calls, but it only exists in PHP 8. Drop it into your code and you have just dropped support for PHP 7.x and older. Use it on purpose, not by habit, if you still promise older versions.
Resolving Compatibility Issues
Now the fixes. None of these are exotic. They are mostly about being explicit where you used to be lazy.
Replacing Deprecated Functions
Swap the removed functions for their modern equivalents. Two you will hit constantly:
Replacing create_function() with Anonymous Functions
<?php
/**
* Example replacing create_function() with an anonymous function.
*
* @param array $items List of items to process.
* @return array Processed items.
*/
$items = array_map(function($item) {
return strtoupper($item);
}, $items);Replacing each() with foreach
<?php
/**
* Replacement for each() using foreach for better compatibility.
*
* @param array $data Array data to process.
*/
foreach ($data as $key => $value) {
// Process each item.
}Handling Stricter Type Validation
To keep TypeError exceptions off your users, cast values to the type you actually expect, especially anything coming from user input or an outside source.
Example of Explicit Type Casting
<?php
/**
* Casts input to integer to avoid TypeError in PHP 8.
*
* @param mixed $number The input number.
* @return int The processed integer.
*/
function process_number($number) {
return (int) $number;
}Addressing Comparison Changes
When the result has to be predictable, check the type yourself or normalize the values before you compare them. Reach for strict comparison (===) so you are testing type as well as value.
Example of Safe Comparison
<?php
/**
* Safe comparison with explicit type checking in PHP 8.
*
* @param mixed $value Value to check.
* @return bool True if comparison is valid.
*/
function is_valid_value($value) {
return $value === '0' || $value === 0;
}Optimizing Plugins for PHP 8
Once the breakage is gone, PHP 8 gives you a few things worth using. Adopt them because they make the code better, not for the badge.
- Utilize the JIT Compiler: If your plugin does heavy math or other CPU-bound work, JIT can help. Find the hot path first. If you cannot point to one, this is not your win.
- Adopt the Nullsafe Operator: The nullsafe operator (
?->) cleans up long null checks. Only reach for it once you have truly dropped support for PHP below 8. - Leverage Named Arguments: Named arguments make calls to functions with a long list of optional parameters far easier to read, and you can skip the ones you do not care about without counting positions.
Testing and Debugging Plugins on PHP 8
You cannot eyeball PHP 8 compatibility. You have to run the code on PHP 8 and watch what happens.
- Enable WP_DEBUG: Turn on debugging in
wp-config.phpwithdefine( 'WP_DEBUG', true );. It surfaces the warnings and errors that point straight at the incompatible lines. - Run PHPUnit Tests: If you have a test suite, run it on a PHP 8 environment. For anything large, automated tests catch what a manual click-through never will.
- Use a Staging Environment: Test on staging before you touch a live site. You find the breakage without a single user finding it first.
- Check Server Logs: Read the PHP error log. A lot of warnings and errors never reach the screen but sit right there in the log, waiting.
Conclusion
PHP 8 is both a chore and a gift. Clear out the removed functions, make your peace with stricter types, and the same plugin comes out faster and cleaner on the other side.
The real payoff is not the new syntax. It is that your plugin keeps working the day a host upgrades, instead of failing on someone’s live store while you are asleep. Test it early, run it on PHP 8 for real, and you get to update on your terms.


