You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP递归函数中如何移除对象数组的多余层级

问题

我正在编写一个生成API JSON响应的函数,JSON内容由CMS生成,初始结构和示例相近。现在需要递归遍历数组的每个['children']元素,移除所有title为“Component drop zone”的层级,并将该层级的子元素直接提升到父层级。

现有代码:

function removePropertiesAndEmptyChildren(&$data) {
    
    foreach ($data as &$item) {
      $remove_keys = [
        'uid',
        'type',
        'enabled',
        'category',
        'status',
        'componentType',
        'selected',
        'isContainer',
        'mimicParent',
        'dropzoneId',
        'iconColor'
      ];
      foreach($remove_keys as $key) {
        if (isset($item[$key])) {
          unset($item[$key]);
        }
      }
      
      if (isset($item['children']) && empty($item['children'])) {
        unset($item['children']);
      }
      if(is_array($item)) {
        $this->removePropertiesAndEmptyChildren($item);
      }
    }
    return $data;
  }

当前函数返回的数组:

[
  {
    "title": "App Bar",
    "componentId": "cpt_***_app_bar",
    "uuid": "e985becb-7dc4-471c-937e-d06858b04a41",
    "parentUid": "root",
    "children": [
      {
        "parentUid": "cpt_***_app_bar",
        "title": "Component drop zone",
        "uuid": "d692d3b0-7434-4b45-93c1-6b9bf610065e"
      }
    ]
  },
  {
    "title": "List View",
    "componentId": "cpt_***_list_view",
    "uuid": "764be577-e1b7-4481-9ca7-0a22a74afa2d",
    "parentUid": "root",
    "children": [
      {
        "parentUid": "cpt_***_list_view",
        "title": "Component drop zone",
        "uuid": "92226f8a-913c-43a0-94e7-f79f77d28104",
        "children": [
          {
            "title": "Column",
            "componentId": "cpt_***_column",
            "uuid": "c15b5a8c-4a7f-4730-bc80-d0396db350f2",
            "parentUid": "component-drop-zone",
            "children": [
              {
                "parentUid": "cpt_***_column",
                "title": "Component drop zone",
                "uuid": "fd0c1a09-f0cb-4694-9f66-508de2ff5a51",
                "children": [
                  {
                    "title": "Hexa Link Button",
                    "componentId": "cpt_***_hexa_link_button",
                    "uuid": "97fe5f5b-8aee-4284-a536-b48c7121a80b",
                    "parentUid": "component-drop-zone"
                  },
                  {
                    "title": "Hexa Link Button",
                    "componentId": "cpt_***_hexa_link_button",
                    "uuid": "69354116-4b35-4f38-bae5-594714518587",
                    "parentUid": "component-drop-zone"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "title": "Pull To Refresh Action",
    "componentId": "cpt_***_pull_to_refresh_action",
    "uuid": "ac227b11-359c-41eb-8fc3-a7bad71995f1",
    "parentUid": "root"
  }
]

期望得到的数组结构:

[
  {
    "title": "App Bar",
    "componentId": "cpt_***_app_bar",
    "uuid": "e985becb-7dc4-471c-937e-d06858b04a41",
    "parentUid": "root"
  },
  {
    "title": "List View",
    "componentId": "cpt_***_list_view",
    "uuid": "764be577-e1b7-4481-9ca7-0a22a74afa2d",
    "parentUid": "root",
    "children": [
      {
        "title": "Column",
        "componentId": "cpt_***_column",
        "uuid": "c15b5a8c-4a7f-4730-bc80-d0396db350f2",
        "parentUid": "component-drop-zone",           
        "children": [
          {
            "title": "Hexa Link Button",
            "componentId": "cpt_***_hexa_link_button",
            "uuid": "97fe5f5b-8aee-4284-a536-b48c7121a80b",
            "parentUid": "component-drop-zone"
          },
          {
            "title": "Hexa Link Button",
            "componentId": "cpt_***_hexa_link_button",
            "uuid": "69354116-4b35-4f38-bae5-594714518587",
            "parentUid": "component-drop-zone"
          }
        ]           
      }
    ]   
  },
  {
    "title": "Pull To Refresh Action",
    "componentId": "cpt_***_pull_to_refresh_action",
    "uuid": "ac227b11-359c-41eb-8fc3-a7bad71995f1",
    "parentUid": "root"
  }
]

我尝试过以下代码但未生效:

$newData = [];
foreach ($array as $parent => $children) {
    foreach ($children as $child => $grandchildren) {
            $newData[$parent] = array_merge($newData[$parent] ?? [], $grandchildren);
        }
    }

    return $newData;

解决方案

你需要调整递归逻辑的顺序,先处理层级替换,再执行属性移除和空字段清理。修改后的函数如下:

function processComponents(&$data) {
    foreach ($data as &$item) {
        // 优先处理children层级替换
        if (isset($item['children']) && is_array($item['children'])) {
            $processedChildren = [];
            foreach ($item['children'] as $child) {
                // 识别并跳过Component dropzone层级,直接提升其子元素
                if ($child['title'] === 'Component drop zone') {
                    if (isset($child['children']) && !empty($child['children'])) {
                        // 递归处理dropzone的子元素,确保深层层级也被处理
                        $this->processComponents($child['children']);
                        $processedChildren = array_merge($processedChildren, $child['children']);
                    }
                } else {
                    // 递归处理普通子元素
                    $this->processComponents([&$child]);
                    $processedChildren[] = $child;
                }
            }
            // 更新children,空数组则移除该字段
            if (!empty($processedChildren)) {
                $item['children'] = $processedChildren;
            } else {
                unset($item['children']);
            }
        }

        // 移除不需要的属性
        $remove_keys = [
            'uid',
            'type',
            'enabled',
            'category',
            'status',
            'componentType',
            'selected',
            'isContainer',
            'mimicParent',
            'dropzoneId',
            'iconColor'
        ];
        foreach($remove_keys as $key) {
            if (isset($item[$key])) {
                unset($item[$key]);
            }
        }
    }
    return $data;
}

关键逻辑说明:

  1. 层级替换:遍历每个item的children时,直接过滤掉title为“Component drop zone”的元素,将其下的子元素合并到父级的children数组中。
  2. 递归穿透:对所有子元素(包括dropzone的子元素)执行递归处理,确保深层嵌套的dropzone也能被正确替换。
  3. 空字段清理:处理完children后,若结果为空则移除该字段,匹配预期输出结构。
  4. 顺序调整:先完成层级处理,再执行属性移除,避免提前删除必要字段影响判断逻辑。

内容的提问来源于stack exchange,提问作者PixelTarget

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:08:08