The PHP Group has introduced PHP 8.5, the latest version of the open source scripting language widely used across the Web, including for websites built with WordPress.
PHP 8.5, released in November, continues the community’s promise to ship major versions every year, along with two years of active support for each new release.
With 8.5 now officially available, we’ve already included it in our annual PHP performance benchmarks, testing across various popular CMS platforms and frameworks.
If you’re gearing up to upgrade your PHP applications to version 8.5, it’s important to understand the key updates—both new features that can enhance your code and legacy aspects that developers are phasing out.
Below, you’ll find an overview of the important changes in PHP 8.5:
Table of Contents
New features and improvements in PHP 8.5
Let’s kick off with the additions to the core language. Most new features originate as Requests for Comments (RFCs), undergo community evaluation, and, if approved, are targeted for upcoming releases like this one.
These are the standout features developers are talking about in PHP 8.5.
Chain function calls with a pipe operator
The new pipe (|>) operator lets you chain function calls, making the process feel more in line with patterns familiar to JavaScript users. The value is passed from left to right through each function in the chain.
Before PHP 8.5, developers achieved similar results by nesting function calls or manually applying each function to the previous one’s return value.
Consider this straightforward example using the new pipe operator:
$text = ' New-in-php-8.4 ';
$result = $text
|> trim(...)
|> (fn($str) => str_replace('4', '5', $str))
|> (fn($str) => str_replace('-', ' ', $str))
|> strtoupper(...);
var_dump($result);
// string(14) "NEW IN PHP 8.5"
(Here, we use the first-class callable syntax (...)—introduced in PHP 8.1—for functions like trim() and strtoupper().)
While the chain could technically be placed on one line, breaking it apart can improve code readability—a key advantage of the new pipe operator.
The equivalent using nested function calls (which reads right to left) would look like:
$text = " New-in-php-8.4 ";
$result = strtoupper(
str_replace(‘-, ' ',
str_replace('4', '5',
trim($text)
)
)
);
Or, prior to PHP 8.5, you might see something like this:
$text = " New-in-php-8.4 ";
$result = trim($text);
$result = str_replace('4', '5', $result);
$result = str_replace(‘-, ' ', $result);
$result = strtoupper($result);
Parse URLs with the new URI extension
Working with URLs (or URIs) is fundamental for web development, but the long-standing parse_url() function has limitations, especially when handling malformed or non-standard input, which can result in errors when parsing or validating addresses.
In response, PHP 8.5 now bundles uriparser and Lexbor libraries. These provide support for RFC 3986 and WHATWG URL standards, respectively, and significantly improve URL parsing and validation capabilities.
To get started with the URI extension’s uriparser library:
$uri = new UriRfc3986Uri("https://kinsta.com/blog/php-8-5/");
echo $uri->getScheme(); // https
echo $uri->getHost(); // kinsta.com
echo $uri->getPath(); // /blog/php-8-5
To use the Lexbor WHATWG URL library instead, try:
$uri = new UriWagWgUrl("https://kinsta.com/blog/php-8-5/");
echo $uri->getScheme(); // https
echo $uri->getUnicodeHost(); // kinsta.com
echo $uri->getAsciiHost(); // kinsta.com
echo $uri->getPath(); // /blog/php-8-5
These snippets are just the beginning. Both libraries in the new URI extension share some overlapping behaviors but also have distinct features.
One helpful point: the RFC 3986 library lets you handle both “raw” and “normalized-decoded” URI formats. This is particularly handy for dealing with percent-encoded content. For example, the URIs below are treated as equivalent in a web browser:
- https://zedkima.com/mykinsta/
- https://zedkima.com/blog/php-8-5/
In older PHP versions, working with rawurldecode() and rawurlencode()—both RFC 3986 compliant—would be the norm. The new URI extension in PHP 8.5, however, is equipped to handle all URI components, whether encoded or plain, right out of the box.
Check out these examples from the RFC for the new parsing API:
$uri = new UriRfc3986Uri("https://%61pple:p%61ss@ex%61mple.com/foob%61r?%61bc=%61bc");
echo $uri->getRawUserInfo(); // %61pple:p%61ss
echo $uri->getUserInfo(); // apple:pass
echo $uri->getRawUsername(); // %61pple
echo $uri->getUsername(); // apple
echo $uri->getRawPassword(); // p%61ss
echo $uri->getPassword(); // pass
echo $uri->getRawHost(); // ex%61mple.com
echo $uri->getHost(); // example.com
echo $uri->getRawPath(); // /foob%61r
echo $uri->getPath(); // /foobar
echo $uri->getRawQuery(); // %61bc=%61bc
echo $uri->getQuery(); // abc=abc
When using the WHATWG library, all URIs are considered “raw”—there’s no alternative for alternate formats, but you do get built-in conversion between ASCII and Unicode where needed.
Get strict with a new max_memory_limit INI directive
Allocating memory to PHP applications can dramatically impact stability. While PHP offers flexibility to control memory usage via configuration settings, those unfamiliar with a server’s architecture may inadvertently cause out-of-memory errors by raising these limits excessively.
The typical approach is to define a memory ceiling in the php.ini file, for example:
// php.ini
memory_limit 128M
On many hosting environments, developers can override memory_limit inside their PHP code with ini_set():
ini_set(‘memory_limit’, ‘256M’);
// Start code that requires up to 256 MB of memory
You can even set it to -1 (i.e., ini_set('memory_limit', '-1')), removing any cap entirely.
This level of control, if misused, can crash apps by letting them exceed hardware limits. To address this risk, PHP 8.5 introduces the max_memory_limit directive, which sets a hard boundary, regardless of any code-level attempts to push the limit upward using ini_set().
Here’s how that looks in a PHP 8.5 php.ini configuration:
// php.ini
max_memory_limit 256M
memory_limit 128M
With max_memory_limit set to 256 MB, here’s the effect in your PHP code:
ini_set('memory_limit', '256M'); // This is OK
ini_set('memory_limit', '512M'); // Fail with warning
ini_set('memory_limit', '-1'); // Fail with warning
Trying to raise the memory limit to 512 MB (or unlimited) will fail; PHP will lock the limit to max_memory_limit and raise a warning. The warning will be visible depending on error reporting settings and will generally also be logged.
As a best practice, in PHP 8.5, check for this new setting in your scripts with ini_get('max_memory_limit') before making adjustments. For earlier PHP versions, that function will return false if the option is not set.
Grab the first or last values in an array
You might be surprised to learn PHP hadn’t previously included built-in functions for directly retrieving the first and last values in an array.
Since PHP 7.3, there have been functions to get the first and last keys—so the typical workflow was to use array_key_first() or array_key_last(), then access the corresponding values:
$array = ["One", "Two", "Three"];
echo $array[array_key_first($array)]; // "One"
PHP 8.5 streamlines this process. New array_first() and array_last() functions let you fetch array values directly.
Here’s how simple it is now:
$array = ["One", "Two", "Three"];
echo array_first($array); // "One"
echo array_last($array); // "Three"
echo array_last([]); // null
If an array is empty, you’ll get null. However, be mindful this doesn’t guarantee the array is empty—an element could explicitly be null:
echo array_last([1, 2, null]); // null
Get reminded to use a function’s return value
PHP 8.5 introduces a #[NoDiscard] attribute. By marking functions with this attribute, you alert users that ignoring the return value could be problematic. If the function’s return value isn’t used, PHP issues a warning.
Take this basic illustration:
#[NoDiscard("this message property will be appended to the built-in warning.")]
function foo(): string {
return 'bar';
}
// Warning:
// The return value of function foo() is expected to be consumed,
// this message property will be appended to the built-in warning.
foo();
// This will not trigger a warning:
$result = foo();
// Also satisfactory is the (void) cast:
(void) foo();
In the above, not consuming the function’s result prompts a warning. Assigning the output to a variable or handling it explicitly prevents that warning.
The RFC for this feature describes practical applications, such as signaling that a function’s return value conveys important error details, and shouldn’t be overlooked.
Other enhancements related to attributes
Alongside #[NoDiscard], PHP 8.5 includes other attribute-related upgrades:
- Attributes can now be applied to constants.
- The
#[Override]attribute can now be set on properties. - The
#[Deprecated]attribute is available for traits and constants. - The new
#[DelayedTargetValidation]attribute can suppress compile-time errors when core or extension attributes are used in the wrong context.
Deprecations and removals in PHP 8.5
Each new PHP release marks some features as deprecated or removed. Relying on deprecated features brings warnings; once removed, these features will trigger fatal errors.
Notable deprecations and removals in PHP 8.5 include:
- The backtick operator (an alias for
shell_exec()) is deprecated. - Non-standard cast names—
(boolean),(integer),(double), and(binary)—are deprecated. Use(bool),(int),(float), and(string)going forward. - The
disable_classesINI setting has been removed due to its negative impact on engine assumptions. - Terminating
casestatements with a semicolon (instead of a colon) is deprecated. - Using
nullas an array offset, or witharray_key_exists(), is now deprecated. Use an empty string instead. - It is no longer allowed to use “array” and “callable” as class alias targets in
class_alias(). - The
__sleep()and__wakeup()magic methods are now soft-deprecated. Use__serialize()and__unserialize()instead. - A warning is triggered when casting
NANto other types. - Destructuring non-arrays (other than null) using
[]orlist()now gives a warning. - PHP now issues a warning when casting floats (or float-like strings) to
intif they’re not representable as such.
Performance Enhancements and JIT Improvements
Beyond new syntax and features, PHP 8.5 continues to optimize performance under the hood. Enhancements to the Just-In-Time (JIT) compiler, first introduced in PHP 8.0, bring further execution speedups—especially in mathematical computations and complex loops encountered in scientific or data-processing workloads. While web apps see modest gains, CLI tasks and long-running scripts may benefit more substantially.
Performance benchmarks show incremental improvements in real-world frameworks such as Laravel, Symfony, and popular CMS like WordPress, Drupal, and Joomla. These gains are often subtle on smaller sites but can translate to measurable reductions in response times and server load at scale.
Expanded Type Safety and Error Diagnostics
PHP 8.5 builds on PHP’s enhanced type system. Expanded type checks and refined error messages make it easier to catch bugs during development rather than at runtime. For instance, internal functions now consistently throw TypeError or ValueError for invalid input, enforcing correct and predictable behavior in typed codebases. This increased strictness also assists modern static analysis tools, further improving developer confidence.
Improved Reflection and Introspection APIs
The reflection API in PHP 8.5 receives enhancements enabling libraries and tools to inspect attribute metadata more efficiently. For example, it’s now easier to retrieve all applied attributes, including those newly possible on constants and properties. This paves the way for frameworks and testing suites to power more robust dependency injection, annotation processing, and code validation features.
Compatibility and Polyfills
Upgrading to PHP 8.5 may require checking for deprecated or removed functionality, especially in legacy code. However, many popular open source libraries such as Symfony Polyfills offer interim support for new features. This allows you to use updated functions and syntax in your codebase while maintaining compatibility with hosts running slightly older PHP versions.
Many hosting environments and platforms (like WordPress plugins or Laravel packages) quickly adapt to new PHP releases, but always check for support statements and perform regression testing before deploying major upgrades to production.
Migration Tips and Best Practices
- Read Deprecation Warnings: Use the
error_reporting(E_DEPRECATED)setting or tools like PHPStan/Psalm to flag and address deprecated usages well ahead of a major upgrade. - Test on Staging Environments: Before switching production servers, replicate your environment and run your full suite of automated and manual tests against PHP 8.5.
- Leverage New Features Gradually: Adopt new operators, functions, and configuration options in incremental updates; avoid mixing too many changes in a single release.
- Monitor Performance and Logs: Keep an eye on application profiling data and logs after upgrade for unexpected issues (e.g., newly triggered warnings or changes in memory consumption).
- Review Framework and CMS Compatibility: Ensure your application dependencies (including plugins and extensions) are compatible or ready for PHP 8.5, especially if you use older or less-common packages.
- Participate in the Community: The PHP internals mailing list and RFC tracker are useful resources for in-depth guidance and understanding the evolution of language standards.
Community Ecosystem: Tools and Libraries Adopting PHP 8.5
Leading frameworks like Laravel, Symfony, and Yii are actively integrating PHP 8.5’s features, providing updated scaffolding and tooling that leverages the latest improvements. Open source libraries in fields from HTTP client handling to testing (e.g., Guzzle, PHPUnit) are also adding support for new syntax and configuration directives introduced in this release.
For WordPress site owners and plugin developers, keep track of the WordPress Core development blog for official PHP version support timelines and compatibility notes. Adoption is proceeding rapidly thanks to the performance and developer experience gains PHP 8.5 brings.
Real-World Example: Refactoring with the Pipe Operator
Consider a real-world refactor. Suppose you have a data cleanup process involving string trimming, capitalization, and hashing user input:
$result = hash('sha256', strtoupper(trim($userInput)));
With the pipe operator, this transforms into:
$result = $userInput
|> trim(...)
|> strtoupper(...)
|> fn($str) => hash('sha256', $str);
This not only clarifies intent for each transformation step but also opens the door to more functional programming patterns in PHP development.
Summary
That covers the main highlights of PHP 8.5. The introduction of the pipe operator and upgraded URI parsing in particular stand out as exciting tools for developers. And yes—those new array_first() and array_last() functions fill a long-missing gap.
Remember, each major PHP version also brings hundreds of smaller improvements. For the complete rundown, review the official PHP 8.5 change list on GitHub.
Be sure to check with your hosting provider for details on making the switch to PHP 8.5 and leveraging these updates in your projects.



