本文目录导读:

在PHP中递归验证数组通常用于处理嵌套的多维数组数据,以下是几种常见的递归验证方案:
基础递归验证函数
<?php
function validateArrayRecursive(array $data, array $rules): array
{
$errors = [];
foreach ($rules as $key => $rule) {
// 检查键是否存在
if (!isset($data[$key])) {
if (isset($rule['required']) && $rule['required']) {
$errors[$key][] = "{$key}字段是必填的";
}
continue;
}
$value = $data[$key];
// 如果是嵌套规则(子数组验证)
if (isset($rule['type']) && $rule['type'] === 'array' && isset($rule['rules'])) {
if (is_array($value)) {
// 递归验证子数组
$childErrors = validateArrayRecursive($value, $rule['rules']);
if (!empty($childErrors)) {
$errors[$key] = $childErrors;
}
} else {
$errors[$key][] = "{$key}必须是数组";
}
} else {
// 常规验证规则
$fieldErrors = validateField($value, $rule, $key);
if (!empty($fieldErrors)) {
$errors[$key] = $fieldErrors;
}
}
}
return $errors;
}
function validateField($value, array $rules, string $fieldName): array
{
$errors = [];
// 类型验证
if (isset($rules['type'])) {
$typeValidators = [
'string' => 'is_string',
'int' => 'is_int',
'float' => 'is_float',
'numeric' => 'is_numeric',
'bool' => 'is_bool',
'email' => function($v) { return filter_var($v, FILTER_VALIDATE_EMAIL) !== false; }
];
if (isset($typeValidators[$rules['type']])) {
$validator = $typeValidators[$rules['type']];
if (!$validator($value)) {
$errors[] = "{$fieldName}必须是{$rules['type']}类型";
}
}
}
// 最小值验证
if (isset($rules['min'])) {
if (is_numeric($value) && $value < $rules['min']) {
$errors[] = "{$fieldName}不能小于{$rules['min']}";
}
if (is_string($value) && strlen($value) < $rules['min']) {
$errors[] = "{$fieldName}长度不能小于{$rules['min']}";
}
}
// 最大值验证
if (isset($rules['max'])) {
if (is_numeric($value) && $value > $rules['max']) {
$errors[] = "{$fieldName}不能大于{$rules['max']}";
}
if (is_string($value) && strlen($value) > $rules['max']) {
$errors[] = "{$fieldName}长度不能大于{$rules['max']}";
}
}
// 正则验证
if (isset($rules['pattern']) && is_string($value)) {
if (!preg_match($rules['pattern'], $value)) {
$errors[] = "{$fieldName}格式不正确";
}
}
// 枚举验证
if (isset($rules['in']) && !in_array($value, $rules['in'])) {
$errors[] = "{$fieldName}必须是以下值之一:" . implode(', ', $rules['in']);
}
return $errors;
}
使用示例
<?php
// 定义验证规则
$rules = [
'name' => [
'type' => 'string',
'required' => true,
'min' => 2,
'max' => 50
],
'age' => [
'type' => 'int',
'required' => true,
'min' => 0,
'max' => 150
],
'email' => [
'type' => 'email',
'required' => true
],
'address' => [
'type' => 'array',
'required' => true,
'rules' => [
'city' => [
'type' => 'string',
'required' => true,
'min' => 2
],
'zip' => [
'type' => 'string',
'pattern' => '/^\d{5}$/'
],
'country' => [
'type' => 'string',
'in' => ['中国', '美国', '日本']
]
]
],
'hobbies' => [
'type' => 'array',
'rules' => [
'*' => [ // * 表示验证数组中的每个元素
'type' => 'string',
'min' => 2,
'max' => 20
]
]
]
];
// 测试数据
$testData = [
'name' => '张三',
'age' => 25,
'email' => 'zhangsan@example.com',
'address' => [
'city' => '北京',
'zip' => '100000',
'country' => '中国'
],
'hobbies' => ['读书', '游泳', '旅游']
];
// 执行验证
$errors = validateArrayRecursive($testData, $rules);
if (empty($errors)) {
echo "验证通过!\n";
} else {
echo "验证失败:\n";
print_r($errors);
}
高级递归验证(支持数组元素验证)
<?php
function validateNestedArray(array $data, array $rules): array
{
$errors = [];
foreach ($rules as $key => $rule) {
$value = $data[$key] ?? null;
// 处理通配符规则(数组每个元素验证)
if ($key === '*') {
if (is_array($value)) {
foreach ($value as $index => $item) {
$itemErrors = validateField($item, $rule, "元素[{$index}]");
if (!empty($itemErrors)) {
$errors[$index] = $itemErrors;
}
}
}
continue;
}
// 处理可选字段
if ($value === null) {
if (isset($rule['required']) && $rule['required']) {
$errors[$key][] = "{$key}是必填的";
}
continue;
}
// 递归处理子数组
if (isset($rule['type']) && $rule['type'] === 'array' && is_array($value)) {
if (isset($rule['rules'])) {
$childErrors = validateNestedArray($value, $rule['rules']);
if (!empty($childErrors)) {
$errors[$key] = $childErrors;
}
}
} else {
$fieldErrors = validateField($value, $rule, $key);
if (!empty($fieldErrors)) {
$errors[$key] = $fieldErrors;
}
}
}
return $errors;
}
使用类封装
<?php
class ArrayValidator
{
private array $errors = [];
public function validate(array $data, array $rules): bool
{
$this->errors = [];
$this->validateRecursive($data, $rules);
return empty($this->errors);
}
public function getErrors(): array
{
return $this->errors;
}
private function validateRecursive(array $data, array $rules, string $path = ''): void
{
foreach ($rules as $key => $rule) {
$currentPath = $path ? "{$path}.{$key}" : $key;
$value = $data[$key] ?? null;
if ($value === null) {
if (($rule['required'] ?? false)) {
$this->addError($currentPath, "{$currentPath}是必填的");
}
continue;
}
// 递归验证子数组
if (isset($rule['type']) && $rule['type'] === 'array' && isset($rule['rules'])) {
if (!is_array($value)) {
$this->addError($currentPath, "{$currentPath}必须是数组");
} else {
$this->validateRecursive($value, $rule['rules'], $currentPath);
}
} else {
$this->validateField($value, $rule, $currentPath);
}
}
}
private function validateField($value, array $rule, string $path): void
{
// 类型验证
if (isset($rule['type'])) {
$typeCheck = [
'string' => is_string($value),
'int' => is_int($value),
'float' => is_float($value),
'numeric' => is_numeric($value),
'bool' => is_bool($value),
'array' => is_array($value),
'email' => filter_var($value, FILTER_VALIDATE_EMAIL) !== false
];
if (isset($typeCheck[$rule['type']]) && !$typeCheck[$rule['type']]) {
$this->addError($path, "{$path}必须是{$rule['type']}类型");
}
}
// 其他验证规则...
if (isset($rule['min'])) {
if (is_string($value) && mb_strlen($value) < $rule['min']) {
$this->addError($path, "{$path}长度不能小于{$rule['min']}");
}
if (is_numeric($value) && $value < $rule['min']) {
$this->addError($path, "{$path}不能小于{$rule['min']}");
}
}
if (isset($rule['max'])) {
if (is_string($value) && mb_strlen($value) > $rule['max']) {
$this->addError($path, "{$path}长度不能大于{$rule['max']}");
}
if (is_numeric($value) && $value > $rule['max']) {
$this->addError($path, "{$path}不能大于{$rule['max']}");
}
}
if (isset($rule['pattern']) && is_string($value)) {
if (!preg_match($rule['pattern'], $value)) {
$this->addError($path, "{$path}格式不正确");
}
}
}
private function addError(string $path, string $message): void
{
if (!isset($this->errors[$path])) {
$this->errors[$path] = [];
}
$this->errors[$path][] = $message;
}
}
// 使用示例
$validator = new ArrayValidator();
$isValid = $validator->validate($testData, $rules);
if (!$isValid) {
print_r($validator->getErrors());
}
关键点说明
- 递归结构:验证规则可以嵌套定义,函数会递归处理子数组
- 路径追踪:记录验证路径,帮助定位错误位置
- 灵活规则:支持类型、长度、范围、正则、枚举等多种验证
- 错误收集:收集所有错误而不是立即返回
- 可选字段:支持required属性控制字段是否为必填
根据实际需求,你可以扩展验证规则(如自定义验证函数、回调验证等)或使用现有的第三方验证库。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播