PHP8 新特性:构造器属性提升使用及注意事项

本篇主要说下 PHP8 构造器属性提升的用法,这个特性对于一些需要在构造器中设置或初始化一些类属性的时候非常有用(包括 publicprotectedprivate ),比如在 PHP7 中你可以这样定义一个类的属性,然后在构造方法中传值。

1
2
3
4
5
6
7
8
9
class Point {
public int $x;
private string $y;

public function __construct(int $x = 0, string $y='') {
$this->x = $x;
$this->y = $y;
}
}

PHP8 中则可以简化为直接在构造函数方法里面定义类的属性

1
2
3
4
5
6
7
8
9
10
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

如果不添加的话是不会作为类属性定义的,除非你在父类中已经定义了构造器属性,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Test {
public function __construct(
public int $x = 0
) {}
}

class Child extends Test {
public function __construct(
$x,
public int $y = 0,
) {
parent::__construct($x);
}
}

或者在 Traits 中使用

1
2
3
4
5
6
trait MyTrait
{
public function __construct(
public string $x,
) {}
}

注意事项

抽象类或接口的构造器方法不能使用构造器属性定义

错误示例:

1
2
3
4
5
6
7
abstract class Test {
abstract public function __construct(private $x);
}

interface Test {
public function __construct(private $x);
}

对象类型的构造器属性不能使用 null 作为默认值

错误示例:

1
2
3
class Test {
public function __construct(public Type $prop = null) {}
}

正确示例:

1
2
3
class Test {
public function __construct(public ?Type $prop = null) {}
}

不支持 callable 类型的构造器属性定义

错误示例:

1
2
3
class Test {
public function __construct(public callable $callback) {}
}

构造器属性不能使用 var 定义

错误示例:

1
2
3
class Test {
public function __construct(var $prop) {}
}

构造器属性定义也不能使用可变参数

错误示例:

1
2
3
class Test {
public function __construct(public string ...$strings) {}
}

构造器属性和类属性不能重复定义

错误示例:

1
2
3
4
5
6
class Test {
public string $prop;
public int $explicitProp;

public function __construct(public string $prop) {}
}

但可以使用构造器属性定义额外的尚未定义过的类属性

1
2
3
4
5
6
7
8
class Test {
public string $prop;
public int $explicitProp;

public function __construct(public int $promoted, int $arg) {
$this->explicitProp = $arg;
}
}

只能使用简单默认值

不可以在参数的默认值中使用函数或者实例化对象。

错误示例:

1
2
3
public function __construct(
public DateTime $date = new DateTime(),
) {}