对象转数组后键名含nul字符是php对属性可见性的底层映射:public属性为普通键名,protected为"\0*\0key",private为"\0class\0key";get_object_vars()仅返回public属性且无前缀。

对象转数组后键名变成 0、"0"、"\0MyClass\0age" 这类形式,不是 bug,是 PHP 对属性可见性的底层映射规则决定的。
public 属性转成普通字符串键
这是最直观的情况:public 属性直接以属性名作为数组键,不加修饰。
例如:
class User {
public $name = 'Alice';
protected $email = 'a@example.com';
}
$obj = new User();
var_dump((array) $obj);
// 输出中会看到: ["name"] => "Alice"
这种键名看着正常,但只是冰山一角——它掩盖了其他属性的处理逻辑。
protected 和 private 属性带不可见字符前缀
PHP 用特殊字符串格式区分作用域,导致键名“奇怪”:
- protected 属性键名为
"\0*\0email"(\0是 ASCII NUL 字符) - private 属性键名为
"\0User\0email"(User是类名)
这些字符在终端或 var_dump 中通常显示为空格或乱码,但实际存在。你无法直接用 $arr['email'] 访问,必须用完整字符串(含 NUL)或反射才能安全读取。
常见错误现象:isset($arr['email']) 返回 false,即使 var_dump 看似有该字段——因为键名根本不是纯字符串 'email'。
(array) 强制转换和 get_object_vars() 行为差异
两者对属性可见性的处理完全不同:
-
(array) $obj:导出所有属性,包括 protected/private,但加前缀 -
get_object_vars($obj):只返回 public 属性,键名干净,无前缀
如果你只需要 public 数据,用 get_object_vars() 更安全;如果需要完整状态(比如调试、序列化前检查),必须接受带前缀的键名,并注意它们不能被常规字符串操作函数直接匹配。
对象转数组后数字键为什么有时是整数、有时是字符串?
这取决于对象属性是否是“数字索引”的动态属性(极少见),但更常见的是你在对象里手动设置了类似 $obj->{0} = 'x' 的 magic 属性。从 PHP 7.2 起,这类数字键在转数组时会保留为整数键(0),而不是字符串 "0";但如果你用 $obj->{'0'} = 'x',它就是字符串键。
关键点:对象本身没有“索引数组”概念,所谓数字键全是通过魔术访问器或动态属性模拟的,行为高度依赖写法和 PHP 版本。
真正容易被忽略的是:这些键名差异不会报错,但会导致 json_encode()、foreach 或数组函数(如 array_keys())行为不一致——尤其是当你试图用字符串键去查一个实际是整数键的值时,会静默失败。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











