Released November 21, 2024. A major update of the PHP language featuring the new URI extension, support for modifying properties while cloning, the Pipe operator, performance improvements, bug fixes, and general cleanup.

What's New in PHP 8.5?

A new major version with powerful features, performance improvements, and much more.

Clone With

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

Before PHP 8.5

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+

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"

Pipe Operator

The Pipe operator provides a more readable way to chain function calls by passing the result of one expression as the first argument to the next function.

Before PHP 8.5

$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+

$input = ' Some kind of string. ';

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

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

#[\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 to improve the safety of APIs where the returned value is important, but where it is easy to forget using the return value by accident.

Before PHP 8.5

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

getPhpVersion(); // No Errors

PHP 8.5+

#[\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)

New URI Extension

As an always-available part of PHP's standard library the new URI extension provides APIs to parse and modify URIs and URLs according to the RFC 3986 and the WHATWG URL standards.

Before PHP 8.5

$components = parse_url("https://php.net/releases/8.5/en.php");
var_dump($components['host']);
// string(7) "php.net"

PHP 8.5+

use Uri\Rfc3986\Uri;

$uri = new Uri("https://php.net/releases/8.5/en.php");
var_dump($uri->getHost());
// string(7) "php.net"

New array_first() and array_last() functions

Simplified array element retrieval with new built-in functions for common operations.

Before PHP 8.5

$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+

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

Closures and First Class Callables in Constant Expressions

PHP 8.5 allows using closures and first-class callables in constant expressions, enabling more powerful and flexible constant definitions.

Before PHP 8.5

final class CalculatorTest extends \PHPUnit\Framework\TestCase
{
    #[DataProvider('subtractionProvider')]
    public function testSubtraction(
        int $minuend,
        int $subtrahend,
        int $result
    ): void
    {
        $this->assertSame(
            $result,
            Calculator::subtract($minuend, $subtrahend)
        );
    }

    public static function subtractionProvider(): iterable
    {
        for ($i = -10; $i <= 10; $i++) {
            yield [$i, $i, 0];
            yield [$i, 0, $i];
            yield [0, $i, -$i];
        }
    }
}

PHP 8.5+

final class CalculatorTest
{
    #[Test\CaseGenerator(static function (): iterable
    {
        for ($i = -10; $i <= 10; $i++) {
            yield [$i, $i, 0];
            yield [$i, 0, $i];
            yield [0, $i, -$i];
        }
    })]
    public function testSubtraction(
        int $minuend,
        int $subtrahend,
        int $result
    )
    {
        \assert(
            Calculator::subtract($minuend, $subtrahend) === $result
        );
    }
}

Persistent cURL Share Handles

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

Before PHP 8.5

final readonly class PhpVersion {
    public function __construct(
        public readonly string $version
    ) {}
}

$php = new PhpVersion('8.5');

var_dump($php);

PHP 8.5+

final readonly class PhpVersion {
    public function __construct(
        public readonly string $version
    ) {}
}

$php = new PhpVersion('8.5');

var_dump($php);

New Classes, Interfaces, and Functions

PHP 8.5 introduces several new classes, interfaces, and functions that expand the language's capabilities.

Property Promotion

Now available for final classes

Attributes for Constants

Attributes are now available for constants

#[\Override] for Properties

The Override attribute now works on properties

#[\Deprecated] for Traits

Deprecation attribute now available for traits

Asymmetric Visibility

Now available for static properties

#[\DelayedTargetValidation]

New attribute for delayed validation

Error Handler Functions

New get_error_handler() and get_exception_handler()

Closure::getCurrent

New method to get current closure

DOM Methods

New getElementsByClassName() and insertAdjacentHTML()

Enchant Functions

New dictionary management functions

grapheme_levenshtein()

New function for grapheme distance calculation

OPcache Function

New opcache_is_script_cached_in_file_cache()

Reflection Methods

New ReflectionConstant::getFileName(), getExtension(), getExtensionName(), getAttributes(), and ReflectionProperty::getMangledName()

Deprecations & Changes

PHP 8.5 continues to refine the language by deprecating older functionalities.

Roadmap

Looking ahead at the future of PHP development and release cycles.

3

PHP 8.3

Nov 2023

Active Support
4

PHP 8.4

Nov 2024

Active Support
5

PHP 8.5

Nov 2025

In Development
0

PHP 9.0

Future

Planned

Each release branch is actively supported for two years from its initial stable release. After this period, each branch is supported for an additional year for critical security issues only.