将带层级的多维配置数组递归转换为含元数据的数据库表结构数组的实现咨询
将带层级的多维配置数组递归转换为含元数据的数据库表结构数组的实现咨询
看起来你需要把一个多层级的配置数组拆解成对应数据库表结构的三个数组(分类、配置项、默认值),还要自动生成ID、父级关联和顺序字段对吧?刚好可以用递归的方式来处理这种嵌套结构,下面是具体的实现方案:
需求拆解
首先明确我们要生成的三个核心结构:
- 分类数组:记录各级配置分类,包含自增ID、父分类ID、分类名称、排序号
- 配置项数组:记录每个具体的配置参数,包含自增ID、所属分类ID、参数名称、类型、描述、排序号
- 默认值数组:记录配置项的默认值,包含自增ID、所属配置项ID、默认值内容
实现思路
因为配置数组是多层嵌套的(一级分类→二级分类→配置项),用递归函数可以自动处理任意深度的层级:
- 初始化三个结果数组和三个自增ID计数器
- 递归遍历原始配置数组,判断当前项是分类还是配置项:
- 如果当前项包含
type字段,判定为配置项,生成对应setting记录,若有default值则同步生成value记录 - 如果不包含
type字段,判定为分类,生成对应category记录,然后递归处理该分类下的所有子项
- 如果当前项包含
- 遍历过程中维护每个层级的排序号,确保分类和配置项的顺序符合原始数组的遍历顺序
完整PHP实现代码
<?php // 你的原始配置数组 $settings = [ 'basic' => [ 'installation_type' => [ 'type' => '["single","cluster"]', 'description' => 'bla blah', 'readonly' => false, 'hidden' => false, 'trigger' => null, 'default' => 'single' ], 'db_master_host' => [ 'type' => 'ip', 'description' => 'Database hostname or IP', 'default' => 'localhost' ], 'db_master_user' => [ 'type' => 'text', 'description' => 'Database username', 'default' => 'test' ], 'db_master_pwd' => [ 'type' => 'secret', 'description' => 'Database user password', ], 'db_master_db' => [ 'type' => 'text', 'description' => 'Database name', 'default' => 'test' ] ], 'provisioning' => [ 'snom' => [ 'snom_prov_enabled' => [ 'type' => 'switch', 'default' => false ], 'snom_m3' => [ 'snom_m3_accounts' => [ 'type' => 'number', 'description' => 'bla blah', 'default' => '0' ] ], 'snom_dect' => [ 'snom_dect_enabled' => [ 'type' => 'switch', 'description' => 'bla blah', 'default' => false ] ] ], 'yealink' => [ 'yealink_prov_enabled' => [ 'type' => 'switch', 'default' => false ] ] ], ]; // 初始化结果数组 $categories = []; $settingsList = []; $values = []; // 自增ID计数器(用引用传递确保递归中持续递增) $catIdCounter = 1; $setIdCounter = 1; $valIdCounter = 1; /** * 递归处理配置数组 * @param array $configData 当前层级的配置数据 * @param int $parentCatId 父分类ID,根层级为0 * @param array $categories 分类结果数组(引用传递) * @param array $settingsList 配置项结果数组(引用传递) * @param array $values 默认值结果数组(引用传递) * @param int $catIdCounter 分类ID计数器(引用传递) * @param int $setIdCounter 配置项ID计数器(引用传递) * @param int $valIdCounter 默认值ID计数器(引用传递) * @param int $catOrder 当前分类层级的起始排序号 */ function processConfig($configData, $parentCatId = 0, &$categories, &$settingsList, &$values, &$catIdCounter, &$setIdCounter, &$valIdCounter, $catOrder = 1) { $currentCatOrder = $catOrder; $currentSetOrder = 1; foreach ($configData as $key => $item) { // 判定规则:包含type字段的是配置项,否则是分类 if (isset($item['type'])) { // 生成配置项记录 $settingsList[$key] = [ 'id' => $setIdCounter, 'catId' => $parentCatId, 'name' => $key, 'type' => $item['type'], 'desc' => $item['description'] ?? '', // 处理可选的描述字段 'order' => $currentSetOrder ]; // 如果存在默认值,生成默认值记录 if (isset($item['default'])) { $values[$key] = [ 'id' => $valIdCounter, 'setId' => $setIdCounter, 'default' => $item['default'] ]; $valIdCounter++; } $setIdCounter++; $currentSetOrder++; } else { // 生成分类记录 $categories[$key] = [ 'id' => $catIdCounter, 'parent' => $parentCatId, 'name' => $key, 'order' => $currentCatOrder ]; // 递归处理当前分类下的子内容 processConfig($item, $catIdCounter, $categories, $settingsList, $values, $catIdCounter, $setIdCounter, $valIdCounter, 1); $catIdCounter++; $currentCatOrder++; } } } // 启动递归处理根层级配置 processConfig($settings, 0, $categories, $settingsList, $values, $catIdCounter, $setIdCounter, $valIdCounter); // 可选:打印结果验证 // echo "<pre>"; // echo "=== 分类数组 ===\n"; // print_r($categories); // echo "\n=== 配置项数组 ===\n"; // print_r($settingsList); // echo "\n=== 默认值数组 ===\n"; // print_r($values); // echo "</pre>"; ?>
关键说明
- 层级判定逻辑:通过
type字段区分分类和配置项,这个规则可以根据你的实际需求调整(比如如果分类也有特殊标识,可以修改判定条件) - 可选字段处理:用
??运算符处理可选的description和default字段,避免未定义索引错误 - 递归兼容性:支持任意深度的分类嵌套,不管是一级、二级还是更多层级都能自动处理
- 排序号维护:每个分类下的子分类和配置项都按原始数组的遍历顺序生成排序号,如果需要按字母序排序,可以在foreach前对
$configData的keys进行排序 - 数据库适配:生成的数组结构可以直接映射到数据库表,你可以根据实际表字段调整数组的键名(比如把
desc改成description)
内容来源于stack exchange
相关产品推荐
相关产品推荐

