对象转数组后,private和protected属性仍存在但键名加特殊前缀:protected为"\0*\0属性名",private为"\0类名\0属性名",需用var_dump或正则提取真实属性名。

对象转数组后,private 和 protected 属性不会消失,但它们的键名会被加上特殊前缀,导致不可直接按原属性名访问。
protected 属性的键名格式
转换后,protected 属性的键名会变成:<p>转换后,protected 属性的键名会变成:<code>\0*\0属性名(即一个空字符 + 星号 + 空字符 + 原属性名)。这个 \0 是 ASCII 码为 0 的空字节,在 var_dump 或 print_r 中可能显示为乱码或不可见,但实际存在于字符串中。
转换后,protected 属性的键名会变成:\0*\0属性名(即一个空字符 + 星号 + 空字符 + 原属性名)。这个 \0 是 ASCII 码为 0 的空字节,在 var_dump 或 print_r 中可能显示为乱码或不可见,但实际存在于字符串中。
<p>转换后,protected 属性的键名会变成:<code>\0*\0属性名(即一个空字符 + 星号 + 空字符 + 原属性名)。这个 \0 是 ASCII 码为 0 的空字节,在 var_dump 或 print_r 中可能显示为乱码或不可见,但实际存在于字符串中。 是 ASCII 码为 0 的空字节,在 var_dump 或 print_r 中可能显示为乱码或不可见,但实际存在于字符串中。
- 例如:
protected $name = 'Alice';→ 转成数组后键名为"\0*\0name" - 用
array_keys()或var_dump()才能看清真实结构 - 不能用
$arr['name']访问,必须用完整带前缀的字符串
private 属性的键名格式
private 属性的键名会变成:\0类名\0属性名(两个空字符夹着完整类名和属性名)。类名包含命名空间(如 App\Models\User),且大小写敏感。
- 例如:
private $id = 123;在App\Models\User类中 → 键名为"\0App\Models\User\0id" - 若类在全局命名空间,键名是
"\0User\0id" - 同样无法通过常规键名访问,需精确匹配整个字符串
为什么这样设计
PHP 这样处理是为了在数组中**保留封装语义**:不破坏访问控制逻辑,同时让调试时能看到所有属性值。它不是为了方便读取,而是为了“不丢失数据”。
-
(array)转换本质是内存结构的浅层映射,不是语义化导出 - 如果只想要 public 属性,应改用
get_object_vars($obj) - 若需统一处理所有属性,得用正则提取真实属性名,或遍历
ReflectionClass











