PHP8 动态属性被弃用兼容方案

news/2024/12/11 17:11:29/

PHP 类中可以动态设置和获取没有声明过的类属性。这些属性不遵循具体的规则,并且需要使用 __get() 和 __set() 魔术方法对动态属性如何读写进行有效控制。

class User {private int $uid;
}$user = new User();
$user->name = 'Foo';

上述代码中,User 类并没有声明 name 属性,不过因为允许使用动态属性,PHP 中可以这样设置。

虽然动态属性在创建类中(比如,非严格类声明中的值对象)提供了更多灵活性,同时也为潜在 bug 和非预期行为提供了可能性。比如,代码中如果出现拼写错误,可能导致设置了不需要的属性,这样的失误可能会因为允许动态属性而被忽视。

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. 类使用 #[AllowDynamicProperties] 注解
  2. stdClass 类及它的子类
  3. 带 __get 和 __set 魔术方法的类

带有 #[AllowDynamicProperties] 注解的类

PHP 8.2 在全局命名空间中引入 #[AllowDynamicProperties] 注解。带有这一注解的类,会通知 PHP 不要在该类对象设置动态属性时发出废弃通知。

子类可以从父类中继承 #[AllowDynamicProperties] 注解。

下面的代码中用 #[AllowDynamicProperties] 注解声明了 User 类,即使动态设置属性也不会发出废弃通知。

+ #[AllowDynamicProperties]class User {private int $uid;}$user = new User();$user->name = 'Foo';

stdClass 类及其子类

PHP 在解码 JSON 对象将数据强制转换成对象时,使用 stdClass 类作为基类。在 PHP 8.2 中,#[AllowDynamicProperties] 注解被添加到 stdClass 类。这意味着在 stdClass 类或者它的子类中设置动态属性,不会发出动态属性废弃通知。

$object = new stdClass();
$object->foo = 'bar';
class User extends stdClass {}$object = new User();
$object->foo = 'bar';

以上的代码片段都不会发出废弃通知,因为 stdClass 类内部有 #[AllowDynamicProperties] 注解。

带 __get 和 __set 魔术方法的类

声明 __set 魔术方法的类也不包含在动态属性废弃中。实际使用中,或许也需要与之对应的 __get 方法使其实际可用。

class User {public function __set(string $name, mixed $value): void {}
}$user = new User();
$user->name = 'test';

上面的代码段不会发出废弃通知,因为 User 类执行了 __set 魔术方法。

注意,在 __set 方法中设置动态属性,仍然会被废弃:

class User {public function __set(string $name, mixed $value): void {$this->{$name} = $value;}
}$user = new User();
$user->name = 'test';
Deprecated: Creation of dynamic property User::$name is deprecated in ... on line ...

将对象数据与 WeakMap 关联

PHP 8.0 中引入了 WeakMap。需要设置动态属性作为辅助数据的,可以考虑使用 WeakMap。这能使代码更加清晰、更好维护,而又能避免动态属性废弃通知。

比如,下面的代码存储了一个叫 processed 的动态属性。这个属性没有在 Event 类中声明,并且也不属于 Event 类。 

$event = new Event();
$event->processed = true; // <-- dynamic property$is_processed = !empty($event->processed);

使用 WeakMap,可以将数据关联到 WeakMap。当 Event 对象脱离作用域后,关联的数据也会被自动移除。

  $event = new Event();
+ $processed_events = new WeakMap();- $event->processed = true; // <-- dynamic property
+ $processed_events[$event] = true;- $is_processed = !empty($event->processed);
+ $is_processed = !empty($processed_events[$event]);

向后兼容性影响

PHP 8.2 中,会发出废弃通知。到 PHP 9.0,动态属性则会导致致命错误


http://www.ppmy.cn/news/1554277.html

相关文章

调度系统:Prefect 结合 Couchbase SQL 执行和调度 SQL 查询脚本

使用 Prefect 管理和调度 Couchbase SQL 脚本的实际例子可以帮助你自动化数据提取、转换和加载&#xff08;ETL&#xff09;任务&#xff0c;尤其是当你需要执行复杂的 SQL 查询&#xff0c;处理来自 Couchbase 数据库的数据时。以下是一个例子&#xff0c;展示如何使用 Prefec…

es实现上传文件查询

es实现上传文件查询 上传文件&#xff0c;获取文件内容base64&#xff0c;使用es的ingest-attachment文本抽取管道转换为文字存储 安装插件 通过命令行安装&#xff08;推荐&#xff09; 1.进入 Elasticsearch 安装目录 2.使用 elasticsearch-plugin 命令安装 bin/elastics…

基于spring boot的高校专业实习管理系统的设计与实现

文末获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 设计题目&#xff1a;基于spring boot的高校专业实习管理系统的设计与实现 摘 要 随着国内市场经济这几十年来的蓬勃发展&#xff0c;突然遇到了从国外传入国内的互联网技术&#xff0c;互联网产业从开…

如何避免缓存击穿?超融合常驻缓存和多存储池方案对比

作者&#xff1a;SmartX 解决方案专家 钟锦锌 很多运维人员都知道&#xff0c;混合存储介质配置可能会带来“缓存击穿”的问题&#xff0c;尤其是大数据分析、数据仓库等需要频繁访问“冷数据”的应用场景&#xff0c;缓存击穿可能会更频繁地出现&#xff0c;影响业务运行。除…

Distance in Tree 树形dp练习(树中两点距离为k的数量板子)

Distance in Tree 题面翻译 题目大意 输入点数为 N N N一棵树 求树上长度恰好为 K K K的路径个数 输入格式 第一行两个数字 N , K N,K N,K,如题意 接下来的 N − 1 N-1 N−1行中,每行两个整数 u , v u,v u,v表示一条树边 ( u , v ) (u,v) (u,v) 输出格式 一个整数 a n…

k8s折腾笔记

k8s折腾笔记 k8s安装、部署、运行demo1.系统环境2.开始安装2.1 先从master节点开始2.2 worker节点 3.遇到的问题4.集群demo k8s安装、部署、运行demo 1.系统环境 两台服务器&#xff0c;都是ubuntu22版本&#xff0c; 一台2核4g&#xff0c;作为master节点 一台2核2g&#xf…

Hyper-V创建虚拟机配置IP等网络配置原理(Linux、Windows为例)

Hyper-V创建虚拟机配置IP等网络配置原理&#xff08;Linux、Windows为例&#xff09; 大家知道Windows系统里面内置了Hyper-V管理器&#xff0c;用来创建和管理本地虚拟机环境。今天我创建了两台虚拟机&#xff0c;一台是CentOS7.9&#xff08;Linux&#xff09;&#xff0c;另…

使用 Streamlit +gpt-4o实现有界面的图片内容分析

在上一篇利用gpt-4o分析图像的基础上&#xff0c;进一步将基于 Python 的 Streamlit 库&#xff0c;结合 OpenAI 的 API&#xff0c;构建一个简洁易用的有界面图片内容分析应用。通过该应用&#xff0c;用户可以轻松浏览本地图片&#xff0c;并获取图片的详细描述。 调用gpt-4o…