PHP 8 来了!朝着正确方向迈出的一步?新功能介绍

2025-06-10

PHP 8 来了!朝着正确方向迈出了一步?

介绍

新功能

pexels发布的照片

介绍

PHP 8 终于来了!

PHP 8.0 是 PHP 语言的一次重大更新,
包含许多新特性和优化,包括命名参数联合类型属性构造函数属性提升匹配表达式空安全运算符JIT,以及类型系统错误处理一致性方面的改进。

在本文中,我们将回顾所有新功能和变化,并分享对每个变化的一些想法,以及 PHP 似乎正在绘制的路线图。

您也可以在官方发布公告中阅读有关这些内容的全部内容。

新功能

命名参数

在 PHP 8 中,调用函数时,可以省略非必需参数,只传递所需的参数。

命名参数示例

function my_awesome_function(string $name, string $value = "", int $expires = 0) {
    ...
}
Enter fullscreen mode Exit fullscreen mode

假设现在我们要调用这个函数,但只指定$name$expires属性。

在 PHP 7 中:

// calling the function. but we only want to specify $name and $expires
my_awesome_function('test', '', time() + 60 * 60 * 2)
Enter fullscreen mode Exit fullscreen mode

在 PHP 8 中:

// calling the function. but we only want to specify $name and $expires
my_awesome_function(name: 'test', expires: time() + 60 * 60 * 2)
Enter fullscreen mode Exit fullscreen mode

我对命名参数的看法

这是一个巧妙且便捷的设计。如今许多语言都支持这种方法调用。

然而,这种设计可能会导致函数违反“单一职责原则”,因为这些方法会因为参数过多而“做太多事情”。所以,一如既往,请谨慎使用 ;-)

属性

属性是这个模块中的新生事物。它本质上是一种直接嵌入到代码中的配置语言。

属性是一种原生的 PHP 语法,它能够在代码中的声明中添加结构化的、机器可读的元数据信息:类、方法、函数、参数、属性等等。

属性示例

在 PHP 7 中(使用 PHPDocs):

class BookController
{
    /**
     * @Route("/api/books/{id}", methods={"GET"})
     */
    public function get($id) { /* ... */ }
}
Enter fullscreen mode Exit fullscreen mode

在 PHP 8 中:

class BookController
{
    #[Route("/api/books/{id}", methods: ["GET"])]
    public function get($id) { /* ... */ }
}
Enter fullscreen mode Exit fullscreen mode

构造函数属性提升

基本思想很简单:抛弃所有类属性和变量赋值,并在构造函数参数前加上 、 或 前缀public。PHPprotectedprivate采用这种新语法,并在实际执行代码之前将其转换为正常的语法。

构造函数属性示例

在 PHP 7 中:

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

在 PHP 8 中:

class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}
Enter fullscreen mode Exit fullscreen mode

我对构造函数属性提升的看法

构造函数属性提升减少了所需的代码量,从而生成更小、更简洁的类。

如果您仍然希望拥有不属于构造函数参数的类属性,您可以按照旧的方式声明它们,然后在构造函数内部实例化(或不实例化)。

联合类型

联合类型是一种为属性/变量声明多种类型的方法。
因此,如果函数参数可以接受stringint值,您现在可以将其声明为string|int

这在 PHP 7 中无法实现,只能使用 PHPDocs(因此它不属于 PHP 核心库,但存在于 PHPDocs 中)。您可以使用在运行时

验证的原生联合类型声明,而无需使用 PHPDoc 注释来声明多种类型的组合

联合类型示例

在 PHP 7 中:

class Book {
  /** @var int|float */
  private $price;

  /**
   * @param float|int $price
   */
  public function __construct($price) {
    $this->price = $price;
  }
}

new Book('test'); // OK at runtime
Enter fullscreen mode Exit fullscreen mode

在 PHP 8 中,由于 Union 类型是 PHP 运行时库和编译器的一部分,因此这将引发错误:

class Book {
  public function __construct(
    private int|float $price
  ) {}
}

new Book('test'); // TypeError
Enter fullscreen mode Exit fullscreen mode

我对 Union 类型的看法

作为SOLID 原则的拥护者,我并不十分支持这项更改。

我可以理解,它确实可以提高速度,并增强我对代码的控制力,但我认为,如果你的代码经常需要使用联合类型作为属性,那么你肯定需要好好考虑一下。

匹配表达式

匹配表达式语法是 PHP 8 中最优秀的功能之一,它switch以多种方式改进了语法。

我们先来比较一下两者。这里有一个经典的switch例子(来自本文的例子):

在 PHP 7 中(使用switch):

switch ($statusCode) {
    case 200:
    case 300:
        $message = null;
        break;
    case 400:
        $message = 'not found';
        break;
    case 500:
        $message = 'server error';
        break;
    default:
        $message = 'unknown status code';
        break;
}
Enter fullscreen mode Exit fullscreen mode

在 PHP 8 中(使用match):

$message = match ($statusCode) {
    200, 300 => null,
    400 => 'not found',
    500 => 'server error',
    default => 'unknown status code',
};
Enter fullscreen mode Exit fullscreen mode

我对匹配表情功能的看法

match将执行严格的类型检查,而不是宽松的检查。这就像使用===而不是==
在我看来,这是一个很好的机会,因为它使代码更严格,更具表现力。

此外,如果您忘记检查某个值,并且没有指定默认分支,PHP 将抛出UnhandledMatchError异常。

这再次提高了严格性,但它可以防止一些细微的错误被忽视。

要解决这个问题,您应该将表达式包装在一个单独的方法中,并通过返回默认值match来处理异常。UnhandledMatchError

空安全运算符

现在,您可以使用新的 nullsafe 运算符来使用链式调用,而无需使用空值检查条件。

当链中某个元素的求值失败时,整个链的执行将中止,并且整个链的求值结果都将为空。

空安全运算符示例

在 PHP 7 中:

$country =  null;

if ($book !== null) {
  $author = $book->author;

  if ($author !== null) {
    $address = $author->getAddress();

    if ($address !== null) {
      $country = $address->country;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

在 PHP 8 中:

$country = $book?->author?->getAddress()?->country;
Enter fullscreen mode Exit fullscreen mode

我对 nullsafe 运算符的看法

我对此百感交集。

当然,这确实很方便,因为它可以减少代码量,而且无疑更易读。

但从全局来看,我们的代码为什么需要如此深入和贪婪地进行检查?

我们的代码是否应该有业务规则来约束这种行为?
所以,这又是一个方便的新功能,但请谨慎使用……

更合理的字符串与数字比较

当与数字字符串进行比较时,PHP 8 使用数字比较。否则,它会将数字转换为字符串并使用字符串比较。

在 PHP 7 中:

0 == 'foobar' // true
Enter fullscreen mode Exit fullscreen mode

在 PHP 8 中:

0 == 'foobar' // false
Enter fullscreen mode Exit fullscreen mode

这无疑是朝着正确方向迈出的一步,但前提是 PHP 正在努力成为一种更严格的语言。

当我们说“equals”时,我们的意思应该是“equals”

我对 PHP 8 的总体看法

PHP 无疑正在努力成为一种更严格、更“严肃”的语言。作为面向对象编程 (OOP)SOLID 原则

的忠实拥护者,我非常乐意并支持这个方向。 此外,正如您在升级指南中看到的,PHP 8 总体上是向后兼容的,因为它不会破坏之前主要版本中的许多功能。太棒了!

因此,让我们尽可能有意识地尝试使用 PHP 的所有新功能,并构建出令人惊叹的东西!

如果您对新版 PHP 感到满意,请查看迁移指南

您对 PHP 8 有何看法?

鏂囩珷鏉ユ簮锛�https://dev.to/pavlosisaris/php-8-is-here-a-step-in-the-right-direction-41ad
PREV
检查目录和文件大小的有用命令
NEXT
Handling complex MVC applications - How to scale and avoid Controller chaos Introduction