Administrator
发布于 2025-10-21 / 0 阅读
0

PHP 8.5 新功能

php-8.5-coming-soon-featured.jpg

PHP 8.5 将于下月 2025 年 11 月 20 日发布,它将包括 Pipe 运算符、新的 URI 扩展、新的 array_first()array_last() 函数等:

Pipe Operator   #管道操作符

管道操作符(Pipe Operator)对于希望将多个可调用代码链在一起的 PHP 开发人员来说,是一个令人兴奋的前景,他们可以通过本地方式将一个值从左到右传递给多个可调用代码:

// Using the pipe operator in PHP 8.5
$result = "Hello World"
    |> htmlentities(...)
    |> str_split(...)
    |> fn($x) => array_map(strtoupper(...), $x)
    |> fn($x) => array_filter($x, fn($v) => $v != 'O');

array_first() 和 array_last() 函数

PHP 8.5 将包含 array_first()array_last() 函数。虽然从表面上看,这些函数似乎不是什么大不了的东西(PHP 社区已经有了用户态实现和多补丁),但这些函数作为 PHP 语言的原生函数早该出现了。

这些函数是对 PHP 7.3 中已经提供的数组键方法的补充:

  • 在 PHP 7.3 中,我们有 array_key_first()array_key_last() 来获取数组的首键和尾键。但我们还没有获取数组首尾值的方法。这比你想象的要难,因为数组的键值不一定是整数,不一定从 0 开始,等等。

  • 现有的 reset()end() 等 "技巧 "在语义上是错误的,因为它们修改了数组的 "内部迭代器"。此外,它也不能在所有类型的表达式中正常工作(例如,从函数/普通数组返回的数组可能会因 by-ref 参数而引起注意)。

  • Using $array[array_key_first($array)] is cumbersome  使用 $array[array_key_first($array)] 非常麻烦

// Function signatures
function array_first(array $array): mixed {}
function array_last(array $array): mixed {}
 
// Examples
array_first(["single element"]); // "single element"
array_last(["single element"]); // "single element"
 
array_first([]); // NULL
array_last([]); // NULL
 
array_first([1 => 'a', 0 => 'b', 3 => 'c', 2 => 'd']); // 'a'
array_last([1 => 'a', 0 => 'b', 3 => 'c', 2 => 'd']); // 'd'
 
$str = "hello";
array_first([&$str, false]); // "hello" (no ref)
array_last([false, &$str]); // "hello" (no ref)

新的 URI 扩展

PHP 8.5 引入了一个新的 URI 扩展,它是一个符合标准的解析器,"同时适用于 RFC 3986 和 WHATWG URL 标准,是新的'URI'扩展中标准库的一个始终可用的部分"。RFC 有很多示例,下面是 PHP 基金会公告中的一个示例,展示了 RFC 3986 Uri 类:

use Uri\Rfc3986\Uri;
 
$url = new Uri('HTTPS://thephp.foundation:443/sp%6Fnsor/');
 
$defaultPortForScheme = match ($url->getScheme()) {
    'http' => 80,
    'https' => 443,
    'ssh' => 22,
    default => null,
};
 
// Remove default ports from URLs.
if ($url->getPort() === $defaultPortForScheme) {
    $url = $url->withPort(null);
}
 
// Getters normalize the URL by default. The `Raw`
// variants return the input unchanged.
 
echo $url->toString(), PHP_EOL;
// Prints: https://thephp.foundation/sponsor/
echo $url->toRawString(), PHP_EOL;
// Prints: HTTPS://thephp.foundation/sp%6Fnsor/

检索当前正在执行的闭包

PHP 8.5 在常量表达式中引入了对闭包的支持,从而可以将默认属性值定义为 Closure 以及其他用例:

function my_array_filter(
    array $array,
    Closure $callback = static function ($item) { return !empty($item); },
) {
    $result = [];
 
    foreach ($array as $item) {
        if ($callback($item)) {
            $result[] = $item;
        }
    }
 
    return $result;
}
 
my_array_filter([
    0, 1, 2,
    '', 'foo', 'bar',
]); // [1, 2, "foo", "bar"]

PHP 致命错误回溯

新的 fatal_error_backtraces 设置可以控制是否显示致命错误的回溯。在 PHP 8.5 中, fatal_error_backtraces 设置将默认为 1 --您不需要配置任何东西就可以获得这些回溯(当然,您也可以禁用它们)。在目前稳定的 PHP 版本(即 PHP 8.4)中,没有回溯的致命错误可能包括解析错误(语法错误)、重复的函数或类、有最大执行时间的无限循环等。

Fatal error: Cannot redeclare class B (previously declared in /srv/app/index.php:11) in /srv/app/b.php on line 3
Stack trace:
#0 /srv/app/index.php(6): require()
#1 /srv/app/index.php(21): A->loadClassB()
#2 {main}

NI Diff Options  #INI 差分选项

PHP 8.5 为 php --ini 标志引入了一个 INI diff 选项,可以轻松识别配置中已更改的 INI 值。 --ini 标志有助于显示已加载的 php.ini 配置文件以及已解析的其他 .ini 文件

$ php --ini=diff
Non-default INI settings:
allow_url_include: "0" -> ""
auto_append_file: (none) -> ""
auto_prepend_file: (none) -> ""
display_errors: "1" -> ""
display_startup_errors: "1" -> ""
enable_dl: "1" -> ""
error_reporting: (none) -> "22527"
...