Jose Jimenez
Jose Jimenez
Software Architect & Developer
> >

PHP 8.5 Stable Release: 'Clone With', #[NoDiscard], and New URL Classes Define the Future

Published in PHP on Sep 30, 2025

PHP 8.5 is no longer just on the horizon; it’s here. With its stable release confirmed for November 20, 2025, and now in its Release Candidate (RC) phase, developers worldwide are getting their first hands-on experience with an update that solidifies PHP's commitment to clean code, immutability, and robust developer tooling. While earlier previews highlighted quality-of-life improvements, the final sprint to release has unveiled some truly transformative features that promise to significantly refine the PHP development experience.

This article takes a fresh look at PHP 8.5, focusing on the most impactful additions, re-evaluating earlier observations, and reminding us of crucial deprecations.

The Big Three: Game-Changing Additions in PHP 8.5 🚀

While a host of improvements land with 8.5, three features stand out as particularly significant for modern PHP development:

1. The clone with Expression: Embracing Immutability

Perhaps the most anticipated and impactful new syntax is the clone with expression.
For years, working with immutable objects, especially those leveraging PHP 8.1’sreadonly` properties, presented a common challenge: how do you "update" a specific property on an object without violating its immutability? The answer often involved awkward workarounds or boilerplate code.

PHP 8.5 solves this elegantly:

1class User
 2{
3 public function __construct(
4 public readonly int $id,
5 public readonly string $name,
6 public readonly string $email
7 ) {}
 8}
 9 
10$user = new User(1, 'Alice', '[email protected]');
11 
12// Old way (pre-PHP 8.5): cumbersome for readonly properties
13// $newUser = new User($user->id, 'Bob', $user->email);
14 
15// PHP 8.5: Clean and concise!
16$updatedUser = clone $user with ['name' => 'Bob'];
17 
18var_dump($updatedUser->name); // string(3) "Bob"
19var_dump($user->name); // string(5) "Alice" - original is untouched

This syntax allows you to clone an object and, in the same breath, override specific properties in the newly created clone. It’s a powerful pattern for functional programming and makes working with immutable data structures a joy.

2. The #[NoDiscard] Attribute: Preventing Accidental Bugs

Silent failures are often the hardest to debug. The #[NoDiscard] attribute is PHP 8.5's answer to a common class of these: ignoring the return value of a function that produces a result.
By marking a function or method with#[NoDiscard]`, you instruct PHP to warn the developer if its return value is not explicitly used.

1class StringHelper
 2{
3 #[NoDiscard]
4 public static function clean(string $text): string
5 {
6 return trim(strip_tags($text));
7 }
 8 
9 public static function process(string $text): void
10 {
11 // ... some processing that doesn't return a value
12 }
13}
14 
15$dirtyInput = " <h1>Hello World!</h1> ";
16 
17StringHelper::clean($dirtyInput); // PHP 8.5 Warning: The return value of StringHelper::clean() is not used.
18// This would be the correct usage:
19$cleaned = StringHelper::clean($dirtyInput);
20echo $cleaned; // Hello World!
21 
22StringHelper::process("some text"); // No warning, as process() returns void.

This attribute is invaluable for pure functions, builder patterns, or any method where the returned value is crucial for the program's correctness. It’s a proactive safety net that catches potential bugs at development time.

3. New URL Handling Classes: Modern Web Standards at Your Fingertips

The internet runs on URLs, but PHP's built-in parse_url() function, while functional, has long been a source of frustration due to its inconsistencies and deviations from modern standards. PHP 8.5 introduces a suite of new, dedicated, and read-only classes for parsing and manipulating URIs and URLs, adhering strictly to RFC 3986 and the WHATWG URL Standard.
`
While specific class names are still stabilizing, the intent is clear: to provide robust, object-oriented, and standard-compliant tools for URL management.

1use Uri\WhatWg\Url; // Example class name, actual may vary slightly
 2 
3$url = new Url('https://user:[email protected]:8080/path/to/page?query=string#fragment');
 4 
5echo $url->host; // www.example.com
6echo $url->port; // 8080
7echo $url->pathname; // /path/to/page
8echo $url->search; // ?query=string
9echo $url->hash; // #fragment
10echo $url->username; // user
11// ... and many more properties and methods

These classes offer a predictable and safe way to handle complex URL structures, crucial for secure and interoperable web applications, moving beyond the quirks of parse_url().

Other Notable Enhancements & Quality-of-Life Improvements ✨

Beyond the big three, PHP 8.5 brings a host of other valuable features:

  • Pipe Operator (|>): As noted in earlier previews, this is still a highly anticipated feature for chaining function calls in a more readable, left-to-right fashion. 'Hello World' |> strtoupper(...) |> trim(...) makes data flow intuitive.
  • New Array Functions (array_first() and array_last()): Complementing array_key_first() and array_key_last(), these new functions simplify retrieving the first or last value of an array directly.
  • Better Error and Exception Handling: get_error_handler() and get_exception_handler() now allow retrieval of active custom handlers, aiding debugging and framework development. Stack traces for fatal errors provide crucial context.
  • max_memory_limit INI Directive: A new system-level INI directive that sets an absolute maximum for the memory_limit, preventing individual scripts from requesting excessive memory even if memory_limit is increased at runtime. Essential for stable shared hosting and container environments.
  • IntlListFormatter Class: A welcome addition to the Intl extension for correctly formatting lists (e.g., "A, B, and C") according to locale-specific grammatical rules.
  • CLI Improvement: php --ini=diff: A handy new command-line flag that outputs only the INI directives that differ from PHP's default settings, making configuration debugging much faster.
  • Closures in Constant Expressions: Enables the use of static fn(...) => ... within class constant declarations or as default values for promoted properties, offering more flexibility for constant definitions.
  • New cURL Function (curl_multi_get_handles()): For those managing multiple asynchronous cURL requests, this function simplifies handle management and debugging.
  • Internationalization Features: The Intl extension receives locale_is_right_to_left() (and Locale::isRightToLeft()), aiding applications supporting RTL languages.

Deprecations and Backward Compatibility Issues ⚠️

As PHP matures, legacy features are retired. While PHP 8.5 continues this trend, the changes are manageable for most:

  • Deprecation of MHASH constants: Transition to the more modern and secure alternatives provided by the Hash extension.
  • Deprecation of non-string values from output handlers: Output handlers should strictly return string values for predictable behavior.
  • Deprecated custom output buffer handlers: Emitting output from custom output buffer handlers is now discouraged in favor of standard mechanisms.

Performance and Outlook ⚡

PHP 8.5 continues the tradition of incremental performance enhancements. While not a revolutionary leap over 8.4, the ongoing optimizations within the Just-In-Time (JIT) compiler and continued core engine improvements contribute to a faster and more memory-efficient language. These gains, however small individually, sum up to a more performant platform for large-scale applications.

The stable release of PHP 8.5 on November 20, 2025, marks another significant milestone for the language. It reinforces PHP's strategic focus on developer experience, robust tooling, and modern coding paradigms. Developers are encouraged to begin testing their applications against the Release Candidate versions to ensure a smooth upgrade path and to fully leverage the powerful new features that promise cleaner, more maintainable, and more expressive PHP code.