get_object_vars() 仅返回当前作用域下可访问的 public 属性,与定义位置无关;类外部调用只显示 public 属性,类内部调用也绝不返回 protected/private 属性;需用 ReflectionObject 配合 setAccessible(true) 获取全部属性。

get_object_vars 在 PHP 8.3 中的行为没有改变,它始终只返回当前作用域下**可访问(accessible)的 public 属性**,不关心属性是否被定义在当前类、父类或 trait 中,只看访问控制和作用域上下文。
为什么“作用域不同返回结果不一样”?
这不是 bug,而是设计如此。get_object_vars() 的返回结果取决于调用它时所在的**作用域(scope)**:
- 在类外部(如全局作用域)调用:只能看到对象的 public 属性;
- 在类内部(如某个 public 方法里)调用:仍只返回 public 属性,哪怕你在 private/protected 方法里调用也一样;
- 它 不会 返回 private 或 protected 属性,哪怕你正在该类内部调用;
- 它 不会 自动反射出继承链中不可见的属性(比如父类的 protected 属性,在子类外部调用 get_object_vars 就看不到)。
想获取所有属性(包括 protected/private)怎么办?
用 ReflectionObject 显式获取,并按需过滤:
$ref = new ReflectionObject($obj);
$props = $ref->getProperties(ReflectionProperty::IS_PUBLIC |
ReflectionProperty::IS_PROTECTED |
ReflectionProperty::IS_PRIVATE);
$result = [];
foreach ($props as $prop) {
$prop->setAccessible(true); // 绕过访问控制
$result[$prop->getName()] = $prop->getValue($obj);
}
注意:setAccessible(true) 是安全的(PHP 7.4+),但仅限当前请求生命周期,不影响实际类定义。
通过 REST API 管理 Kibana 保存的对象(仪表板、Lens 可视化等)。适用于:① 以编程方式创建、更新、删除仪表板和 Lens 可视化。
立即学习“PHP免费学习笔记(深入)”;
常见误用场景与建议
- 别指望 get_object_vars() 替代 var_dump() 或调试器 —— 它本就不是为“全量查看”设计的;
- 序列化、API 输出等场景,应明确用 __serialize() 或自定义 toArray() 方法,而不是依赖 get_object_vars();
- 如果需要“当前类可见的所有属性”,可以写一个辅助方法,结合 get_class_vars() 和 get_object_vars(),再手动合并 parent::class 的 public 属性(但注意:不能直接拿到父类 protected);
- PHP 8.3 没新增作用域相关逻辑,如果你发现行为变化,大概率是代码中混用了 __get()、__isset()、动态属性(PHP 8.2+ 动态属性默认禁用)或属性类型变更导致的。
简单对比示例
假设有一个类:
class User {
public $name = 'Alice';
protected $age = 30;
private $token = 'xyz';
}
那么:
-
var_dump(get_object_vars(new User())); → 只输出
['name' => 'Alice']; - var_dump((new ReflectionObject(new User()))->getProperties()); → 返回全部三个属性的 ReflectionProperty 对象,可进一步读取。


















