使用构造函数属性提升

除了即时编译器(JIT),PHP 8 引入的最大新功能之一就是构造函数属性提升。这一新特性在 __construct() 方法签名中结合了属性声明和参数列表,并分配了默认值。在本节中,您将学习如何大幅减少属性声明以及 __construct() 方法签名和主体中所需的编码量。

属性提升语法

调用构造函数属性提升所需的语法与 PHP 7 及更早版本中使用的语法相同,但有以下不同:

  • 需要定义可见性级别

  • 不必事先明确声明属性

  • 不必在 __construct() 方法的主体中进行赋值

下面是一个使用构造函数属性提升的代码示例:

Unresolved include directive in modules/ROOT/pages/section01/ch01/ch1-01.adoc - include::example$ch01/php8_prop_promo.php[]

执行前面的代码块时,输出如下:

object(Test)#1 (3) {
    ["id"]=> int(999)
    ["token"]=> int(0)
    ["name"]=> string(0) ""
}

这表明已使用默认值创建了 Test 类型的实例。现在,让我们看看这一功能如何节省大量的编码工作。

使用属性提升来减少代码

在传统的 OOP PHP 类中,需要完成以下三件事:

  1. 声明属性,如下:

    /repo/src/Php8/Image/SingleChar.php
    namespace Php7\Image;
    class SingleChar {
        public $text = '';
        public $fontFile = '';
        public $width = 100;
        public $height = 100;
        public $size = 0;
        public $angle = 0.00;
        public $textX = 0;
        public $textY = 0;
  2. 确定 __construct() 方法签名中的属性及其数据类型,如下所示:

    const DEFAULT_TX_X = 25;
    const DEFAULT_TX_Y = 75;
    const DEFAULT_TX_SIZE = 60;
    const DEFAULT_TX_ANGLE = 0;
    public function __construct(
        string $text,
        string $fontFile,
        int $width = 100,
        int $height = 100,
        int $size = self::DEFAULT_TX_SIZE,
        float $angle = self::DEFAULT_TX_ANGLE,
        int $textX = self::DEFAULT_TX_X,
        int $textY = self::DEFAULT_TX_Y)
  3. __construct() 方法的主体中,为属性赋值,如下所示:

    {
        $this->text = $text;
        $this->fontFile = $fontFile;
        $this->width = $width;
        $this->height = $height;
        $this->size = $size;
        $this->angle = $angle;
        $this->textX = $textX;
        $this->textY = $textY;
        // other code not shown
    }

随着构造函数参数数量的增加,所需的工作量也会大大增加。当使用构造函数属性提升时,完成与前面所示相同的工作所需的代码量将减少到原来的三分之一。

现在让我们来看看前面所示的代码块,但它是用 PHP 8 这一强大的新功能重写的:

// /repo/src/Php8/Image/SingleChar.php
// not all code shown
public function __construct(
    public string $text,
    public string $fontFile,
    public int $width = 100,
    public int $height = 100,
    public int $size = self::DEFAULT_TX_SIZE,
    public float $angle = self::DEFAULT_TX_ANGLE,
    public int $textX = self::DEFAULT_TX_X,
    public int $textY = self::DEFAULT_TX_Y)
    { // other code not shown }

令人惊奇的是,在 PHP 7 和更早版本中需要 24 行代码,而使用 PHP 8 的这一新功能后,只需 8 行代码!

您完全可以在构造函数中加入其他代码。不过,在许多情况下,构造函数的属性提升可以处理通常在 __construct() 方法中完成的所有工作,这意味着您完全可以将其留空 ({ })。

在下一节中,你将了解到一种名为属性的新功能。