本篇主要说下PHP8构造器属性提升的用法,这个特性对于一些需要在构造器中设置或初始化一些类属性的时候非常有用(包括`public`、`protected`和`private`),比如在PHP7中你可以这样定义一个类的属性,然后在构造方法中传值。 ~~~php class Point { public int $x; private string $y; public function __construct(int $x = 0, string $y='') { $this->x = $x; $this->y = $y; } } ~~~ 在PHP8中则可以简化为直接在构造函数方法里面定义类的属性 ~~~php class Point { public function __construct(public int $x = 0, private string $y = '') { // 你可以在构造器中直接输出类的x和y属性的值(也就是传入的x和y变量的值) var_dump($this->x); var_dump($this->y); } } ~~~ 不过需要注意的是构造器属性只能在构造器方法中定义(好像是废话),而且必须添加`public`/`protected`/`private`,如果不添加的话是不会作为类属性定义的,除非你在父类中已经定义了构造器属性,比如: ~~~php class Test { public function __construct( public int $x = 0 ) {} } class Child extends Test { public function __construct( $x, public int $y = 0, public int $z = 0, ) { parent::__construct($x); } } ~~~ 在实际使用过程中,还有些细节需要注意。 ### 抽象类或接口的构造器方法不能使用构造器属性定义 ~~~php abstract class Test { // 错误 abstract public function __construct(private $x); } interface Test { // 错误 public function __construct(private $x); } ~~~ 但Traits中是允许使用的 ``` trait MyTrait { public function __construct( public string $a, ) {} } ``` ### 对象类型的构造器属性不能使用`null`作为默认值 如果你的构造器属性的类型是一个对象,那么不可以使用`null`作为参数默认值 ~~~php class Test { // 错误 public function __construct(public Type $prop = null) {} } ~~~ 但可以使用 ~~~php class Test { // 正确 public function __construct(public ?Type $prop = null) {} } ~~~ ### 不支持`callable`类型的构造器属性定义 ~~~php class Test { // 错误 public function __construct(public callable $callback) {} } ~~~ ### 构造器属性不能使用`var`定义 ~~~php class Test { // 错误 public function __construct(var $prop) {} } ~~~ ### 构造器属性定义也不能使用可变参数 ~~~php class Test { // Error: Variadic parameter. public function __construct(public string ...$strings) {} } ~~~ ### 构造器属性和类属性不能重复定义 比如 ~~~php class Test { public string $prop; public int $explicitProp; // Error: Redeclaration of property. public function __construct(public string $prop) {} } ~~~ 但你可以使用构造器属性定义额外的尚未定义过的类属性 ~~~php class Test { public string $prop; public int $explicitProp; // Correct public function __construct(public int $promotedProp, int $arg) { $this->explicitProp = $arg; } } ~~~ ### 只能使用简单默认值 比如,你不可以在参数的默认值中使用函数或者实例化对象。 ``` public function __construct( public string $name = 'Brent', // 错误 public DateTime $date = new DateTime(), ) {} ``` 更多的用法可以自行研究。