PHP 7.3 中 (array) 强转或 get_object_vars() 无法获取 __get 动态属性值,因其仅返回显式声明的 public 属性;应手动实现 toArray() 方法,结合真实属性与白名单动态字段,安全触发 __get 并避免递归。

PHP 7.3 中,带有 __get 魔术方法的对象不能直接用 (array) 强转或 get_object_vars() 获取动态属性值,因为这些方式只返回对象的**实际定义的属性(public 成员)**,而不会触发 __get。要“正确转为数组”,关键在于:你想要的是「可读取的全部键值对」,包括由 __get 动态提供、但未显式声明的属性。
明确哪些属性应被包含
先理清业务逻辑:__get($name) 通常用于懒加载、计算属性、代理访问等。不是所有被 __get 支持的键都适合导出为数组(比如 __get('password_hash') 就不该暴露)。建议在类中定义一个白名单(如 $exportable 数组)或约定命名规则(如以 get 开头的方法对应可导出字段)。
手动实现 toArray() 方法(推荐)
这是最清晰、可控、可测试的方式。在类中添加一个公共方法:
- 显式列出需导出的字段名(静态属性 +
__get支持的逻辑字段) - 对每个字段,优先尝试用
isset($this->$key)或property_exists()检查是否为真实属性;否则走$this->$key触发__get - 避免无限递归(例如
__get内部又调用toArray)
示例:
public function toArray()
{
$data = [];
// 真实 public 属性(不含 private/protected)
foreach (get_object_vars($this) as $key => $value) {
$data[$key] = $value;
}
// 显式声明的可导出动态字段
$dynamicKeys = ['full_name', 'age', 'status_text'];
foreach ($dynamicKeys as $key) {
if (!array_key_exists($key, $data)) {
$data[$key] = $this->$key; // 自动触发 __get
}
}
return $data;
}
使用反射 + __get 模拟(慎用)
若无法修改原类,且必须通用处理,可用反射获取类中定义的 __get 方法,再结合预设字段列表调用。但注意:
- 反射无法知道哪些键是
__get实际支持的——除非方法内部有注释、配置或固定模式(如支持所有config_*键) - 直接遍历猜测的键名(如
['name', 'email', 'id'])再尝试读取,可能触发意外副作用(如__get('log')写日志) - 不推荐用于生产环境的关键数据导出
避免踩坑的操作
-
不要用
(array)$obj:只会得到真实 public 属性,__get完全不生效 -
不要依赖
get_object_vars():同上,且对 private/protected 属性无效 -
不要在
__get里返回引用或资源:转数组后可能丢失或出错 -
注意类型一致性:
__get返回null、object、array时,要决定是否递归转换(如用json_encode(json_decode(...), true)不可靠)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











