PHP 8.3中含__get/__set的类仍触发动态属性弃用通知?
PHP 8.3中__set内赋值触发动态属性弃用警告的原因及解决方法
核心原因:魔法方法豁免不覆盖类内部直接创建动态属性的场景
PHP 8.2起的动态属性弃用规则里,带__get/__set的类享有豁免,指的是外部代码通过$obj->xxx = $val这类方式访问未声明属性时,会触发__set方法,不会被判定为创建动态属性。但如果在__set方法内部直接执行$this->$property_name = $value,这属于在类内部主动创建未声明的动态属性,这种场景不在豁免范围内——此时你绕过了魔法方法的逻辑,直接操作类的属性空间,PHP会判定这是创建动态属性的行为,因此在8.3中触发了弃用警告(8.2对该场景的检测相对宽松)。
这并非PHP文档疏漏,而是对魔法方法豁免规则的理解偏差导致的。
正确的实现方式
要贴合魔法方法的设计逻辑,同时规避弃用警告,建议用内部存储统一管理动态属性,示例代码如下:
class MyClass { private array $dynamicProps = []; public function __get($name) { return $this->dynamicProps[$name] ?? null; } public function __set($name, $value) { $this->dynamicProps[$name] = $value; } }
这种写法既通过魔法方法处理外部属性访问,又不会创建真正的动态属性,自然不会触发弃用警告。
关于#[AllowDynamicProperties]注解的作用
该注解用于明确允许类拥有动态属性,添加后理论上$this->$property_name = $value不会触发警告,但这违背了使用__get/__set的初衷——既然用魔法方法就是为了统一管理属性访问,没必要再直接创建动态属性。更推荐用内部数组存储的方式,既符合规范,也能兼容未来PHP版本的变化。
内容的提问来源于stack exchange,提问作者Hagen von Eitzen
相关产品推荐
相关产品推荐

