PHP 8.1 即将到来
PHP 8.1 目前正在积极开发中,将于2021年11 月 25 日发布。请记住,如果核心开发团队(例如)添加额外的 Beta 版本,此日期仍可能会更改。我们已经了解新功能、性能改进、更改和弃用;所以让我们一一介绍。
1
Enums(枚举)
枚举将在 PHP 8.1 中添加!
添加枚举将是 PHP 的重大改进,因此我非常期待看到枚举在 PHP 8.1 中出现。为了让您快速预览它们的外观,这里有一个代码示例:
enum Status {
case Pending;
case Active;
case Archived;
}
这就是它们的使用方式:
class Post
{
public function __construct(private Status $status = Status::Pending;)
{}
public function setStatus(Status $status): void
{
// …
}
}
$post->setStatus(Status::Active);
2
Fibers(纤程)
Fibers——又名“绿色线程” ——是一种管理并行性的低级机制。您可能不会直接在您的应用程序中使用它们,但是像 Amphp 和 ReactPHP 这样的框架会大量使用它们。
这是使用纤维的简单示例:
$fiber = new Fiber(function (): void {
$valueAfterResuming = Fiber::suspend('after suspending');
// …
});
$valueAfterSuspending = $fiber->start();
$fiber->resume('after resuming');
3
性能改进
Dmitry Stogov 对 opcache 进行了一些改进,他称之为“继承缓存”。此功能允许缓存类之间的链接,就像从 PHP 7.4 开始可以预加载链接的类一样。
由于这一变化,Dmitry 报告了 5% 到 8% 的性能提升,这是 PHP 8.1 中需要注意的一个很好的小细节。
4
使用字符串键重写数组
PHP 7.4 中已经允许数组解包,但它只适用于数字键。之前不支持字符串键的原因是因为对于如何合并数组重复项没有达成任何共识。RFC 通过遵循以下语义干净地解决了这个问题array_merge:
$array1 = ["a" => 1];
$array2 = ["b" => 2];
$array = ["a" => 0, ...$array1, ...$array2];
var_dump($array); // ["a" => 1, "b" => 2]
5
类构造赋值
这个 RFC 允许你new
在函数定义中使用关键字作为默认参数,以及在属性参数和其他地方。
class MyController {
public function __construct(
private Logger $logger = new NullLogger(),
) {}
}
请注意,此 RFC 仍在投票中,但很明显它会通过。
6
只读属性
类属性可以标记为只读,这意味着它们只能写入一次。
class PostData {
public function __construct(
public readonly string $title,
public readonly DateTimeImmutable $date,
) {}
}
在初始化后尝试更改只读属性将导致错误:
$post = new Post('Title', /* … */);
$post->title = 'Other';
Error: Cannot modify readonly property Post::$title
请注意,此 RFC 仍在投票中,但很明显它会通过。
7
可调用对象语法
您现在可以通过调用可调用对象并将其...
作为参数传递来从可调用对象创建闭包:
function foo(int $a, int $b) { /* … */ }
$foo = foo(...);
$foo(a: 1, b: 2);
请注意,此 RFC 仍在投票中,但很明显它会通过。
8
新的never类型
该never
类型可用于指示函数将实际停止程序流。这可以通过抛出异常、调用exit
或其他类似函数来完成。
function dd(mixed $input): never
{
// dump
exit;
}
never
不同之处void
在于void
仍然允许程序继续。这似乎是一个新奇的功能,但它实际上对静态分析器来说是一个非常有用的功能。
9
新的array_is_list方法
您可能偶尔不得不处理这个问题:确定数组的键是否按数字顺序排列,从索引 0 开始。就像json_encode
决定数组应该被编码为数组还是对象一样。
PHP 8.1 添加了一个内置函数来确定数组是否是具有这些下标的列表:
$list = ["a", "b", "c"];
array_is_list($list); // true
$notAList = [1 => "a", 2 => "b", 3 => "c"];
array_is_list($notAList); // false
$alsoNotAList = ["a" => "a", "b" => "b", "c" => "c"];
array_is_list($alsoNotAList); // false
10
最终类常量
PHP 中的类常量可以在继承过程中被覆盖:
class Foo
{
public const X = "foo";
}
class Bar extends Foo
{
public const X = "bar";
}
从 PHP 8.1 开始,您可以将这样的常量标记为final
以防止出现这种情况:
class Foo
{
final public const X = "foo";
}
class Bar extends Foo
{
public const X = "bar";
Fatal error: Bar::X cannot override final constant Foo::X
}
11
限制$GLOBALS使用
对如何$GLOBALS
使用的微小更改将对所有数组操作的性能产生重大影响。Nikita 在RFC 中很好地解释了问题和解决方案。更改意味着某些边缘情况无法再使用$GLOBALS
. “不再支持写入作为一个整体的 $GLOBALS。以下所有内容都会产生编译时错误”:
$GLOBALS = [];
$GLOBALS += [];
$GLOBALS =& $x;
$x =& $GLOBALS;
unset($GLOBALS);
最重要的是,通过$GLOBALS
引用传递会产生一个运行时错误:
by_ref($GLOBALS); // Run-time error
Nikita 分析了 Packagist 上排名前 2000 的软件包,仅发现了 23 个会受此更改影响的案例。我们可以得出这样的结论——从技术上讲,这种变化的影响很小,这就是内部人员决定在 PHP 8.1 中添加它的原因。
12
其他小改动
每次发布时,都会对语言进行一些非常小的更改。所有这些都列在GitHub 上的升级指南和小的弃用 RFC 中,如果您想了解每个小细节,请务必查看。
以下是最重要变化的摘要:
MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH
不再有效果MYSQLI_STORE_RESULT_COPY_DATA
不再有效果PDO::ATTR_STRINGIFY_FETCHES
现在也适用于布尔值
当使用模拟的准备语句时,PDO MySQL 和 Sqlite 结果集中的整数和浮点数将使用原生 PHP 类型而不是字符串返回
像
htmlspecialchars
和htmlentities
现在这样的函数也'
默认转义为'
; 格式错误的 UTF-8 也将被替换为 unicode 字符,而不是导致空字符串的
hash
,hash_file
并hash_init
增加了一个额外的参数给他们所谓的$options
,它有一个默认值[]
,这样就不会影响到你的代码对
MurmurHash3
和的新支持xxHash
PHP 8.1 的更新还有很多,公众号篇幅有限我也不一一讲解了,主要是排版太痛苦了[Doge],不过现在 PHP 也开始往强类型和协程方向迭代,还是挺值得期待的。
如果觉得文章不错欢迎点赞和转发,关注本公众号不定期推送PHP技术文章。