PHP 7.3无内置object_to_array函数,需自定义:基础版用(array)$obj+array_map支持简单嵌套;进阶版用ReflectionObject处理私有/保护属性并清理键名;防循环引用版加入spl_object_id追踪。

PHP 7.3 中没有内置的 object_to_array 函数,但你可以轻松写一个健壮、可复用的自定义函数,把对象(包括嵌套对象、StdClass、自定义类)转为关联数组。关键在于处理递归、循环引用、不可访问属性和特殊类型(如 Closure、资源)。
基础版:支持 StdClass 和简单嵌套
适用于大多数场景,比如 API 返回的 JSON 解码后对象(json_decode($json, false) 得到的对象):
function object_to_array($obj) {
if (!is_object($obj) && !is_array($obj)) {
return $obj;
}
if (is_object($obj)) {
$obj = (array) $obj;
}
return array_map('object_to_array', $obj);
}
说明:
• (array)$obj 是 PHP 的对象转数组快捷方式,会把 public 属性转为键值对;
• 对 protected/private 属性,会变成 "\0*\0key" 或 "\0ClassName\0key" 格式键名,需额外处理(见进阶版);
• array_map 保证嵌套结构也递归转换。
进阶版:兼容私有/保护属性 + 去除不可见字符键名
使用反射(ReflectionObject)安全读取所有属性,包括 private/protected,并清理键名:
通过 REST API 管理 Kibana 保存的对象(仪表板、Lens 可视化等)。适用于:① 以编程方式创建、更新、删除仪表板和 Lens 可视化。
function object_to_array($obj, $recursive = true) {
if (!is_object($obj) && !is_array($obj)) {
return $obj;
}
if (is_object($obj)) {
$arr = [];
$reflection = new ReflectionObject($obj);
$properties = $reflection->getProperties();
foreach ($properties as $prop) {
$prop->setAccessible(true); // 允许读取私有/保护属性
$key = $prop->getName();
$value = $prop->getValue($obj);
// 清理 PHP 自动添加的不可见前缀(如 \0*\0name)
$cleanKey = preg_replace('/^\x00.*?\x00/', '', $key);
$arr[$cleanKey] = $recursive ? object_to_array($value) : $value;
}
return $arr;
}
// 是数组:递归处理每个值
$result = [];
foreach ($obj as $k => $v) {
$result[$k] = $recursive ? object_to_array($v) : $v;
}
return $result;
}
注意点:
• $prop->setAccessible(true) 在 PHP 7.3 是安全且推荐的方式;
• 不要直接用 (array)$obj 后再正则清理键——反射更准确、可控;
• 若对象有 __toString() 或 JsonSerializable,该函数不自动调用,如需特殊序列化逻辑,应单独处理。
防循环引用增强版(可选)
当对象间存在双向引用(如 A→B 且 B→A),递归会导致无限循环或内存溢出。加入引用追踪:
立即学习“PHP免费学习笔记(深入)”;
function object_to_array($obj, $seen = []) {
if (!is_object($obj) && !is_array($obj)) {
return $obj;
}
$objId = spl_object_id($obj);
if (is_object($obj) && isset($seen[$objId])) {
return null; // 或返回 '[circular reference]'
}
if (is_object($obj)) {
$seen[$objId] = true;
$arr = [];
$reflection = new ReflectionObject($obj);
foreach ($reflection->getProperties() as $prop) {
$prop->setAccessible(true);
$key = preg_replace('/^\x00.*?\x00/', '', $prop->getName());
$arr[$key] = object_to_array($prop->getValue($obj), $seen);
}
return $arr;
}
// 数组分支(同样检查子项是否为已见对象)
$result = [];
foreach ($obj as $k => $v) {
$result[$k] = is_object($v) ? object_to_array($v, $seen) : object_to_array($v, $seen);
}
return $result;
}
说明:
• spl_object_id() 是 PHP 7.2+ 稳定可靠的对象唯一标识;
• 适合处理 ORM 实体、树形结构等易出现循环引用的场景;
• 生产环境建议加上此防护,尤其在处理用户传入或外部接口数据时。
实用建议与避坑提醒
- 避免用
json_encode + json_decode(..., true)替代——会丢失方法、资源、Closure,且对 DateTime 等对象转成字符串,精度和类型信息可能丢失 - 若目标是序列化给前端,优先考虑让对象实现
JsonSerializable接口,更语义化、可控 - 对于 Laravel/Eloquent 模型,直接用
$model->toArray(),它已内置属性过滤和关系处理 - 不要在函数里硬编码跳过某些属性名(如
password),敏感字段应在模型层或 DTO 中显式控制
不复杂但容易忽略:始终检查输入类型、处理空值、明确是否递归、以及是否需要保留原始键名格式。按需选用基础版或反射版即可满足绝大多数 PHP 7.3 项目需求。


















