New URI Extension RFC
$components = parse_url("https://php.net/releases/8.5/en.php");
var_dump($components['host']);
// string(7) "php.net"
use Uri\Rfc3986\Uri;
$uri = new Uri("https://php.net/releases/8.5/en.php");
var_dump($uri->getHost());
// string(7) "php.net"
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.
The secure and standards-compliant URI parsing is powered by the uriparser (RFC 3986) and Lexbor (WHATWG URL) libraries.
Clone With RFC
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
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"
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.
Pipe Operator RFC
$input = ' Some kind of string. ';
$output = strtolower(
str_replace(['.', '/', '…'], '',
str_replace(' ', '-',
trim($input)
)
)
);
var_dump($output);
// string(19) "some-kind-of-string"
$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
RFC
function getPhpVersion(): string
{
return 'PHP 8.4';
}
getPhpVersion(); // No Errors
#[\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)
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.
The associated (void)
cast can be used to indicate that a value is intentionally unused.
Closures and First Class Callables in Constant Expressions RFC RFC
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];
}
}
}
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 RFC RFC
$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);
$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);
The following new classes and functions are available:
CurlSharePersistentHandle
curl_multi_get_handles()
curl_share_init_persistent()
New array_first()
and
array_last()
functions
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 = null;
foreach ($php as $key => $version) {
if ($version['state'] === 'upcoming') {
$upcomingRelease = $version;
break;
}
}
var_dump($upcomingRelease);
$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()
andDom\Element::insertAdjacentHTML()
methods are available - New
enchant_dict_remove_from_session()
andenchant_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()
, andReflectionProperty::getMangledName()
methods are available