如何验证多维dataArray是否符合动态定义的structureArray结构?
PHP 无限层级数组结构验证实现
核心思路
用递归函数处理嵌套结构,天然适配无限层级的验证需求,无需手动编写多层循环。先明确structureArray的规则约定,再通过递归遍历逐一验证dataArray的键、值类型及子结构。
结构规则约定
根据需求,定义structureArray的验证规则:
- 键:代表
dataArray中允许/要求存在的字段名 - 值:决定对应字段的验证逻辑:
- 索引数组:表示该字段的取值必须是数组内的枚举值(严格匹配类型)
- 关联数组:表示该字段必须是数组,且需匹配关联数组定义的子结构;若关联数组包含
'*' => true标记,则允许该层级存在任意额外键值对 - 非数组值:表示该字段的值必须与结构中的值严格类型匹配
验证函数实现
function validateStructure($data, $structure) { // 枚举值验证:结构是索引数组时,检查数据是否在枚举内 if (is_array($structure) && array_is_list($structure)) { return in_array($data, $structure, true); } // 子结构验证:结构是关联数组时,数据必须是数组 if (is_array($structure) && !array_is_list($structure)) { if (!is_array($data)) { return false; } // 检查是否允许额外键值对 $allowExtra = isset($structure['*']) && $structure['*'] === true; unset($structure['*']); // 验证结构要求的所有必填键(若要改为可选,见下文说明) foreach ($structure as $key => $subStruct) { if (!isset($data[$key]) || !validateStructure($data[$key], $subStruct)) { return false; } } // 不允许额外键时,检查数据的键是否都在结构定义内 if (!$allowExtra) { foreach ($data as $key => $_) { if (!isset($structure[$key])) { return false; } } } return true; } // 基础类型验证:严格匹配值和类型 return $data === $structure; }
使用示例
1. 定义结构规则
$structureArray = [ 'firstpart' => [1, 2, 3, 4], // 仅允许这四个数字 'another' => 'myval', // 必须是字符串'myval' 'something' => [ 'first' => [1, 2, 3], // 枚举值验证 'secon' => [ '*' => true, // 允许该层级添加任意额外键值对 'my' => 'this' // 必须存在'my'键,值为'this' ] ] ];
2. 验证合法数据
$validData = [ 'firstpart' => 2, 'another' => 'myval', 'something' => [ 'first' => 3, 'secon' => [ 'my' => 'this', 'extra_key' => '任意值', // 因允许额外键,合法 'sub_dim' => ['嵌套' => '也支持'] ] ] ]; var_dump(validateStructure($validData, $structureArray)); // 输出 bool(true)
3. 验证非法数据
$invalidData = [ 'firstpart' => 5, // 不在枚举范围内 'another' => '错误值', 'something' => [ 'first' => '3', // 类型不匹配(字符串 vs 数字) 'secon' => [ 'my' => '错误内容' ] ] ]; var_dump(validateStructure($invalidData, $structureArray)); // 输出 bool(false)
可选调整:允许字段非必填
如果不需要强制要求结构中的字段必须存在,仅在字段存在时验证格式,只需修改验证必填键的代码:
将
if (!isset($data[$key]) || !validateStructure($data[$key], $subStruct)) { return false; }
改为
if (isset($data[$key]) && !validateStructure($data[$key], $subStruct)) { return false; }
内容的提问来源于stack exchange,提问作者4Usol
相关产品推荐
相关产品推荐

