Released Nov 20, 2025

Smarter, Faster, Built for Tomorrow.

PHP 8.5 is a major update of the PHP language. It contains many new features, such as the new URI extension, support for modifying properties while cloning, the Pipe operator, performance improvements, bug fixes, and general cleanup.

Key Features in PHP 8.5

PHP 8.5 is here, faster, cleaner, and built for developers.

The Pipe Operator

PHP 8.5 introduces the |> operator to chain callables left-to-right, passing values smoothly through multiple functions natively.

Array First & Last Functions

Retrieve the first or last value of any array effortlessly, without changing internal pointers or writing extra helper code.

Clone with

Clone objects and update properties with the new clone() syntax, making the "with-er" pattern simple for readonly classes.

New URI Extension

PHP 8.5 adds a built-in URI extension to parse, normalize, and handle URLs following RFC 3986 and WHATWG standards.

#[\NoDiscard] Attribute

The #[\NoDiscard] attribute warns when a return value isn’t used, helping prevent mistakes and improving overall API safety.

Persistent cURL Share Handles

New CurlSharePersistentHandle class, curl_multi_get_handles(), curl_share_init_persistent() functions.

The Pipe Operator

PHP 8.5 adds a new operator, the pipe operator |> to chain multiple callables from left to right, taking the return value of the left callable and passing it to the right.

PHP 8.4 and older
$input = ' Some kind of string. ';

$output = strtolower(
    str_replace(['.', '/', '…'], '',
        str_replace(' ', '-',
            trim($input)
        )
    )
);

var_dump($output);
// string(19) "some-kind-of-string"
PHP 8.5 NEW RFC ↗
$input = ' Some kind of string. ';

$output = $input
    |> trim(...)
    |> (fn($str) => str_replace(' ', '-', $str))
    |> (fn($str) => str_replace(['.', '/', '…'], '', $str))
    |> strtolower(...);

var_dump($output);
// string(19) "some-kind-of-string"

Array First & Last Functions

PHP 8.5 adds two new functions for retrieving the first and last values of an array. These functions complement the array_key_first and array_key_last functions.

PHP 8.4 and older
$php = [
    'php-82' => ['state' => 'security', 'branch' => 'PHP-8.2'],
    'php-83' => ['state' => 'active', 'branch' => 'PHP-8.3'],
    'php-84' => ['state' => 'active', 'branch' => 'PHP-8.4'],
    'php-85' => ['state' => 'upcoming', 'branch' => 'PHP-8.5'],
];

$upcomingRelease = null;
foreach ($php as $key => $version) {
    if ($version['state'] === 'upcoming') {
        $upcomingRelease = $version;
        break;
    }
}

var_dump($upcomingRelease);
PHP 8.5 NEW RFC ↗
$php = [
    'php-82' => ['state' => 'security', 'branch' => 'PHP-8.2'],
    'php-83' => ['state' => 'active', 'branch' => 'PHP-8.3'],
    'php-84' => ['state' => 'active', 'branch' => 'PHP-8.4'],
    'php-85' => ['state' => 'upcoming', 'branch' => 'PHP-8.5'],
];

$upcomingRelease = array_first(
    array_filter(
        $php,
        static fn($version) => $version['state'] === 'upcoming'
    )
);

var_dump($upcomingRelease);

Clone With

It is now possible to update properties during object cloning by passing an associative array with the updated to the clone() function. This enables straight-forward support of the "with-er" pattern for readonly classes.

PHP 8.4 and older
final readonly class PhpVersion
{
    public function __construct(
        public string $version = 'PHP 8.4',
    ) {}

    public function withVersion(string $version): self
    {
        $newObject = clone $this;
        $newObject->version = $version;

        return $newObject;
    }
}

$version = new PhpVersion();

var_dump($version->version);
// string(7) "PHP 8.4"

var_dump($version->withVersion('PHP 8.5')->version);
// Fatal error: Uncaught Error: Cannot modify readonly property PhpVersion::$version
PHP 8.5 NEW RFC ↗
final readonly class PhpVersion
{
    public function __construct(
        public string $version = 'PHP 8.4',
    ) {}

    public function withVersion(string $version): self
    {
        return clone($this, [
            'version' => $version,
        ]);
    }
}

$version = new PhpVersion();

var_dump($version->version);
// string(7) "PHP 8.4"

var_dump($version->withVersion('PHP 8.5')->version);
// string(7) "PHP 8.5"

var_dump($version->version);
// string(7) "PHP 8.4"

New URI Extension

PHP 8.5 adds a built-in URI extension to parse, normalize, and handle URLs following RFC 3986 and WHATWG standards.

PHP 8.4 and older
$components = parse_url("https://php.net/releases/8.5/en.php");

var_dump($components['host']);
// string(7) "php.net"
PHP 8.5 NEW RFC ↗
use Uri\Rfc3986\Uri;

$uri = new Uri("https://php.net/releases/8.5/en.php");

var_dump($uri->getHost());
// string(7) "php.net"

#[\NoDiscard] Attribute

Adding the #[\NoDiscard] attribute makes PHP warn if a function’s return value isn’t used, improving API safety. Use the (void) cast to mark values intentionally unused.

PHP 8.4 and older
function getPhpVersion(): string
{
    return 'PHP 8.4';
}

getPhpVersion(); // No Errors
PHP 8.5 NEW RFC ↗
#[\NoDiscard]
function getPhpVersion(): string
{
    return 'PHP 8.5';
}

getPhpVersion();
// Warning: The return value of function getPhpVersion() should either be used or intentionally ignored by casting it as (void)

Persistent cURL Share Handles

The Curl extension in PHP 8.5 adds a new function named curl_multi_get_handles that returns an array of CurlHandle objects from a CurlMultiHandle object.

PHP 8.4 and older
$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);

$ch1 = curl_init('https://php.net/');
curl_setopt($ch1, CURLOPT_SHARE, $sh);
curl_exec($ch1);

$ch2 = curl_init('https://thephp.foundation/');
curl_setopt($ch2, CURLOPT_SHARE, $sh);
curl_exec($ch2);
PHP 8.5 NEW RFC ↗
$sh = curl_share_init_persistent([
    CURL_LOCK_DATA_DNS,
    CURL_LOCK_DATA_CONNECT
]);

$ch1 = curl_init('https://php.net/');
curl_setopt($ch1, CURLOPT_SHARE, $sh);
curl_exec($ch1);

$ch2 = curl_init('https://thephp.foundation/');
curl_setopt($ch2, CURLOPT_SHARE, $sh);
curl_exec($ch2);

New Classes, Interfaces, and Functions

  • Property Promotion is now available for final
  • Attributes are now available for constants
  • Attribute #[\Override] now works on properties
  • Attribute #[\Deprecated] available for traits
  • Asymmetric Visibility for Static Properties
  • New #[\DelayedTargetValidation] attribute is available
  • New get_error_handler(), get_exception_handler() functions are available.
  • New Closure::getCurrent method is available.
  • New Dom\Element::getElementsByClassName() and Dom\Element::insertAdjacentHTML() methods are available.
  • New enchant_dict_remove_from_session() and enchant_dict_remove() functions are available.
  • New grapheme_levenshtein() function is available.
  • New opcache_is_script_cached_in_file_cache() function is available.
  • New ReflectionConstant::getFileName(), ReflectionConstant::getExtension(), ReflectionConstant::getExtensionName(), ReflectionConstant::getAttributes(), and ReflectionProperty::getMangledName() methods are available.

Deprecations & BC breaks

  • All MHASH_* constants deprecated
  • Non-canonical scalar type casts (boolean|double|integer|binary) deprecated
  • Returning non-string values from a user output handler is deprecated
  • Emitting output from custom output buffer handlers is deprecated