PHP8 新特性解析

PHP8.0 新特性解析

前言

今天在群内有朋友问我 php8.0 可以搞了不, 我说不知道,乘着被人催,这就来更新一下博客文章。

1611566390(1).png

刚好宝塔也有 php8.0 可以安装,顺手就安装了,本来是准备给博客升级到 php8.0 的,升级完后发现因为新特性导致一些功能无法正常运行,无奈只能换回 php7.4。接下来我们来看看 php8.0 的新特新吧。

PHP 8.0 值得关注的改进包括

1、PHP 8.0 引入了备受期待的 Just In Time (JIT) 编译器,能够进一步提高 PHP 脚本的执行速度

2、PHP 8.0 合并了诸多性能优化

3、JSON 支持现在被视为语言的核心部分,始终可用,而不是作为可选模块

4、支持 named 参数,因为它们能够指定参数名称而不是其确切顺序

5、支持类/属性/函数/方法/参数/常量的结构化元数据的属性(或在其他语言中也称为注释或修饰符)

6、支持可以指示多种不同类型的联合类型,这些类型可以用作参数或函数的返回类型

7、支持静态返回类型

8、str_contains()函数是一种检查字符串是否包含在另一个字符串中的简便方法,而不必使用strpos等。与之相似的是新的str_starts_with()和str_ends_with()函数

9、添加了Nullsafe运算符,作为在方法上应用空合并行为的快速简便的方法

10、相比较 PHP 7.4 稳定版,PHP 8.0 在性能上大约改进了 10%,但是至少在某些方面,JIT 可以提供更多的性能

上方内容引用于(PHP 8.0 值得关注的改进包括): https://www.php.cn/toutiao-464912.html

PHP 8.0 特性解释

命名参数

  • 仅仅指定必填参数,跳过可选参数。
  • 参数的顺序无关、自己就是文档(self-documented)
# php7
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

# php8.0
htmlspecialchars($string, double_encode: false);

注释

现在可以用 PHP 原生语法来使用结构化的元数据,而非 PHPDoc 声明。

# php7
class PostsController
{
    /**
     * @Route("/api/posts/{id}", methods={"GET"})
     */
    public function get($id) { /* ... */ }
}

# php8.0
class PostsController
{
    #[Route("/api/posts/{id}", methods: ["GET"])]
    public function get($id) { /* ... */ }
}

构造器属性提升

更少的样板代码来定义并初始化属性。

# php7
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;
  }
}

# php8
class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}

联合类型

相较于以前的 PHPDoc 声明类型的组合, 现在可以用原生支持的联合类型声明取而代之,并在运行时得到校验。

# php7
class Number {
  /** @var int|float */
  private $number;
  /**
   * @param float|int $number
   */
  public function __construct($number) {
    $this->number = $number;
  }
}
new Number('NaN'); // Ok

#php8
class Number {
  public function __construct(
    private int|float $number
  ) {}
}
new Number('NaN'); // TypeError

Match 表达式

新的 match 类似于 switch,并具有以下功能:

  • Match 是一个表达式,它可以储存到变量中亦可以直接返回。
  • Match 分支仅支持单行,它不需要一个 break; 语句。
  • Match 使用严格比较。
# php7
switch (8.0) {
  case '8.0':
    $result = "Oh no!";
    break;
  case 8.0:
    $result = "This is what I expected";
    break;
}
echo $result;
//> Oh no!

# php8
echo match (8.0) {
  '8.0' => "Oh no!",
  8.0 => "This is what I expected",
};
//> This is what I expected

Nullsafe 运算符

现在可以用新的 nullsafe 运算符链式调用,而不需要条件检查 null。 如果链条中的一个元素失败了,整个链条会中止并认定为 Null。

#php7
$country =  null;
if ($session !== null) {
  $user = $session->user;
  if ($user !== null) {
    $address = $user->getAddress();
 
    if ($address !== null) {
      $country = $address->country;
    }
  }
}

# php8
$country = $session?->user?->getAddress()?->country;

字符串与数字的比较更符合逻辑

PHP 8 比较数字字符串(numeric string)时,会按数字进行比较。 不是数字字符串时,将数字转化为字符串,按字符串比较。

# php7
0 == 'foobar' // true
    
# php8
0 == 'foobar' // false

内部函数类型错误的一致性

现在大多数内部函数在参数验证失败时抛出 Error 级异常。

# php7
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

# php8
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

即时编译

该功能在发布前就已经大火,大家在讨论与关注的一个功能。

PHP 8 引入了两个即时编译引擎。 Tracing JIT 在两个中更有潜力,它在综合基准测试中显示了三倍的性能, 并在某些长时间运行的程序中显示了 1.5-2 倍的性能改进。 典型的应用性能则和 PHP 7.4 不相上下。

关于 JIT 对 PHP 8 性能的贡献

scheme.jpg

更多的相关信息

官方:https://www.php.net/releases/8.0/zh.php

添加新评论