PHP Logo
8.5
Release Candidate

Discover What's New in PHP 8.5

Explore the exciting new features and improvements in the upcoming PHP 8.5 release.

From URL parsing APIs to pipe operators and clone with syntax, PHP 8.5 brings powerful new capabilities to developers.

Download PHP 8.5 RC1

What's new in 8.4

PHP 8.5 New Features

Add RFC 3986 and WHATWG URL compliant API

RFC
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"
Uri\UriException, Uri\InvalidUriException, Uri\UriComparisonMode, Uri\Rfc3986\Uri, Uri\WhatWg\InvalidUrlException, Uri\WhatWg\UrlValidationErrorType, Uri\WhatWg\UrlValidationError, and Uri\WhatWg\Url are now available.

Clone with v2

RFC
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

RFC
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"

New #[\NoDiscard] Attribute

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

First Class Callables in constant expressions

RFC RFC
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 handle improvement

RFC RFC
PHP < 8.5
$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
$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 CurlSharePersistentHandle class, curl_multi_get_handles(), curl_share_init_persistent() functions are available.

New array_first() and array_last() functions

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

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 and backward compatibility breaks

  • No major deprecations announced yet
  • Check the release notes for detailed information