PHP 8.0 是PHP语言的一次主版本更新。它包含很多新特性及优化,包括具名参数、联合类型、注解、构造函数属性提升、match表达式、空指针安全运算符、JIT,以及类型系统、错误处理和一致性方面的改进。
Just-In-Time compilation
PHP 8 引入了两套JIT编译引擎:
- Tracing JIT(在二者中最有前途)
- Function JIT
具名参数
- 调用函数/方法时,仅需指定必要的参数,跳过无需赋值的参数;
- 具名参数的写法不受参数定义顺序约束,因为有自解释作用;
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
htmlspecialchars($string, double_encode: false);
注解(Attributes)
替代了PHPDoc注解的写法,成为PHP原生语法。
class PostsController
{
/**
* @Route("/api/posts/{id}", methods={"GET"})
*/
public function get($id) { /* ... */ }
}
class PostsController
{
#[Route("/api/posts/{id}", methods: ["GET"])]
public function get($id) { /* ... */ }
}
构造函数属性提升
定义和初始化类属性时,减少大量样板代码。
class Point {
public float $x;
public float $y;
public float $z;
public function __construct(
float $x = 0.0,
float $y = 0.0,
float $z = 0.0
) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
}
class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
联合类型
替代了PHPDoc注解的写法,现在可以原生语法声明联合类型,且会在运行时执行相应验证。
class Number {
/** @var int|float */
private $number;
/**
* @param float|int $number
*/
public function __construct($number) {
$this->number = $number;
}
}
new Number('NaN'); // Ok
class Number {
public function __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
Match 表达式
match 与 switch 类似,相比有如下特点:
- match 是表达式,即它的执行结果可被存储到变量中或作为返回值
- match 的分支语句仅支持单行语句、且无需break;
- match 执行类型严格比较
switch (8.0) {
case '8.0':
$result = "Oh no!";
break;
case 8.0:
$result = "This is what I expected";
break;
}
echo $result;
//> Oh no!
echo match (8.0) {
'8.0' => "Oh no!",
8.0 => "This is what I expected",
};
//> This is what I expected
空指针安全运算符
使用新的空指针安全运算符,可以使用链式调用了,不再需要用以前的null条件判断。在链式写法中的某一级元素为null时,整个链式执行终止并返回null。
$country = null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
$country = $session?->user?->getAddress()?->country;
更理性的字符串与数值比较
当一个数值与另一个字符串格式的数值进行比较时,PHP 8 采用数值比较;否则,将该数值转换为字符串进行字符串比较。
0 == 'foobar' // true
0 == 'foobar' // false
内部函数类型一致性错误
更多的内部函数其参数验证失败时会抛出Error异常。
strlen([]); // Warning: strlen() expects parameter 1 to be string, array given
array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0
strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given
array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0
类型系统及错误处理机制改进
- 针对算术与位操作更严格的类型检测;
- 抽象trait方法验证
- ...
其它语法变化与改进
- ...
新的类、接口及函数
- Weak Map 类
- Stringable 接口
- str_contains(), str_starts_with(), str_ends_with()
- fdiv()
- get_debug_type()
- get_resource_id()
- token_get_all() 对象实现
- 新 DOM Traversal 及 Manipulation APIs