在PHP类中,有可能动态地设置和检索未被声明的类属性。这些属性不遵守特定的(类似于类型化的属性),它需要使用__get()和__set()魔法方法来有效地防止或控制动态属性的设置和检索方式。

class User {
    private int $uid;
}

$user = new User();
$user->name = 'Foo';

在上面的片段中,User类没有声明一个名称为name的属性,但由于允许动态属性,PHP允许设置它。

虽然动态属性提供了创建类的灵活性,如没有严格的类声明的价值对象,但它为应用程序中潜在的错误和意外行为提供了可能性。例如,由于PHP默许所有的动态属性,设置属性的语句中的一个错别字可能会被忽略。

在 PHP 8.2 及以后的版本中,为未声明的类属性设置一个值是被废弃的,并且在应用程序执行过程中第一次设置该属性时,会发出废弃通知。

class User {
    private int $uid;
}

$user = new User();
$user->name = 'Foo';
Deprecated: Creation of dynamic property User::$name is deprecated in ... on line ...

从类中设置属性也会发出废弃通知:

class User {
    public function __construct() {
        $this->name = 'test';
    }
}

new User();
Deprecated: Creation of dynamic property User::$name is deprecated in ... on line ...

动态属性有合法的用例,比如从动态JSON响应中得到的值对象,或者允许任意值的配置对象。

理想情况下,类应该在类中声明动态属性以避免废弃通知。不需要用一个属性类型来声明该属性。

豁免的动态属性模式

这种废弃有三种例外情况。使用下面的方法之一可以避免废弃的通知。

  1. Classes with #[AllowDynamicProperties] attribute.
  2. stdClass and its sub-classes
  3. Classes with __get and __set magic methods

参考: https://php.watch/versions/8.2/dynamic-properties-deprecated#exempt