PHP 8.5.0 Released!
Released Nov 20, 2025

Smarter, Faster, Built for Tomorrow.

PHP 8.5 is a major update of the PHP language, with new features including the URI extension, Pipe operator, and support for modifying properties while cloning.

Key Features in PHP 8.5

Faster, cleaner, and built for developers.

URI Extension

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

Pipe Operator

The |> operator enables chaining callables left-to-right, passing values smoothly through multiple functions without intermediary variables.

Clone With

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

#[\NoDiscard] Attribute

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

Closures and First-Class Callables in Constant Expressions

Static closures and first-class callables can now be used in constant expressions, such as attribute parameters.

Persistent cURL Share Handles

Handles can now be persisted across multiple PHP requests, avoiding the cost of repeated connection initialization to the same hosts.

URI Extension

The new always-available URI extension provides APIs to securely parse and modify URIs and URLs according to the RFC 3986 and the WHATWG URL standards.

Powered by the uriparser (RFC 3986) and Lexbor (WHATWG URL) libraries.

Learn more about the backstory of this feature in The PHP Foundation’s blog.

PHP 8.4 and older
$components = parse_url('https://php.net/releases/8.4/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"

Pipe Operator

The pipe operator allows chaining function calls together without dealing with intermediary variables. This enables replacing many "nested calls" with a chain that can be read forwards, rather than inside-out.

Learn more about the backstory of this feature in The PHP Foundation’s blog.

PHP 8.4 and older
$title = ' PHP 8.5 Released ';

$slug = strtolower(
    str_replace('.', '',
        str_replace(' ', '-',
            trim($title)
        )
    )
);

var_dump($slug);
// string(15) "php-85-released"
PHP 8.5 NEW RFC
$title = ' PHP 8.5 Released ';

$slug = $title
    |> trim(...)
    |> (fn($str) => str_replace(' ', '-', $str))
    |> (fn($str) => str_replace('.', '', $str))
    |> strtolower(...);

var_dump($slug);
// string(15) "php-85-released"

Clone With

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

PHP 8.4 and older
readonly class Color
{
    public function __construct(
        public int $red,
        public int $green,
        public int $blue,
        public int $alpha = 255,
    ) {}

    public function withAlpha(int $alpha): self
    {
        $values = get_object_vars($this);
        $values['alpha'] = $alpha;

        return new self(...$values);
    }
}

$blue = new Color(79, 91, 147);
$transparentBlue = $blue->withAlpha(128);
PHP 8.5 NEW RFC
readonly class Color
{
    public function __construct(
        public int $red,
        public int $green,
        public int $blue,
        public int $alpha = 255,
    ) {}

    public function withAlpha(int $alpha): self
    {
        return clone($this, [
            'alpha' => $alpha,
        ]);
    }
}

$blue = new Color(79, 91, 147);
$transparentBlue = $blue->withAlpha(128);

#[\NoDiscard] Attribute

By adding the #[\NoDiscard] attribute to a function, PHP will check whether the returned value is consumed and emit a warning if it is not. This allows improving the safety of APIs where the returned value is important, but it's easy to forget using the return value by accident.

The associated (void) cast can be used to indicate that a value is intentionally unused.

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

getPhpVersion(); // No warning
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)

Closures and First-Class Callables in Constant Expressions

Static closures and first-class callables can now be used in constant expressions. This includes attribute parameters, default values of properties and parameters, and constants.

PHP 8.4 and older
final class PostsController
{
    #[AccessControl(
        new Expression('request.user === post.getAuthor()'),
    )]
    public function update(
        Request $request,
        Post $post,
    ): Response {
        // ...
    }
}
PHP 8.5 NEW RFC RFC
final class PostsController
{
    #[AccessControl(static function (
        Request $request,
        Post $post,
    ): bool {
        return $request->user === $post->getAuthor();
    })]
    public function update(
        Request $request,
        Post $post,
    ): Response {
        // ...
    }
}

Persistent cURL Share Handles

Unlike curl_share_init(), handles created by curl_share_init_persistent() will not be destroyed at the end of the PHP request. If a persistent share handle with the same set of share options is found, it will be reused, avoiding the cost of initializing cURL handles each time.

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);

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

curl_exec($ch);
PHP 8.5 NEW RFC RFC
$sh = curl_share_init_persistent([
    CURL_LOCK_DATA_DNS,
    CURL_LOCK_DATA_CONNECT,
]);

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

// This may now reuse the connection from an earlier SAPI request
curl_exec($ch);

array_first() and array_last() functions

The array_first() and array_last() functions return the first or last value of an array, respectively. If the array is empty, null is returned (making it easy to compose with the ?? operator).

PHP 8.4 and older
$lastEvent = $events === []
    ? null
    : $events[array_key_last($events)];
PHP 8.5 NEW RFC
$lastEvent = array_last($events);

Additional features and improvements

  • Fatal Errors (such as an exceeded maximum execution time) now include a backtrace.
  • Attributes can now target constants.
  • #[\Override] attribute can now be applied to properties.
  • #[\Deprecated] attribute can be used on traits and constants.
  • Static properties now support asymmetric visibility.
  • Properties can be marked as final using constructor property promotion.
  • Added Closure::getCurrent() method to simplify recursion in anonymous functions.
  • setcookie() and setrawcookie() now support the "partitioned" key.
  • New get_error_handler() and get_exception_handler() functions are available.
  • New Dom\Element::getElementsByClassName() and Dom\Element::insertAdjacentHTML() methods are available.
  • Added grapheme_levenshtein() function.
  • New #[\DelayedTargetValidation] attribute can be used to suppress compile-time errors from core and extension attributes that are used on invalid targets.

Deprecations and backward compatibility breaks

  • The backtick operator as an alias for shell_exec() has been deprecated.
  • Non-canonical cast names (boolean), (integer), (double), and (binary) have been deprecated. Use (bool), (int), (float), and (string) instead, respectively.
  • The disable_classes INI setting has been removed as it causes various engine assumptions to be broken.
  • Terminating case statements with a semicolon instead of a colon has been deprecated.
  • Using null as an array offset or when calling array_key_exists() is now deprecated. Use an empty string instead.
  • It is no longer possible to use "array" and "callable" as class alias names in class_alias().
  • The __sleep() and __wakeup() magic methods have been soft-deprecated. The __serialize() and __unserialize() magic methods should be used instead.
  • A warning is now emitted when casting NAN to other types.
  • Destructuring non-array values (other than null) using [] or list() now emits a warning.
  • A warning is now emitted when casting floats (or strings that look like floats) to int if they cannot be represented as one.
To Top