
本文介绍如何使用 php 对用户提交的 json 数据进行结构化校验,确保其字段名、类型与预定义的表单 schema 严格一致,防止非法键名或格式写入数据库 json 字段。
本文介绍如何使用 php 对用户提交的 json 数据进行结构化校验,确保其字段名、类型与预定义的表单 schema 严格一致,防止非法键名或格式写入数据库 json 字段。
在构建动态表单系统时,常将表单结构(如字段名、类型、约束)以 JSON Schema 形式存储于配置中,并将用户填写结果以关联数组或对象形式存入数据库的 JSON 类型字段(如 MySQL 的 JSON 列)。此时,仅靠数据库层面无法校验字段合法性——必须在应用层对提交数据进行模式一致性校验:即验证 details 中每个对象的唯一键是否存在于 formDefinition 中,且不得出现未声明的字段。
✅ 核心校验逻辑
关键在于:提交数据中的所有键,都必须在 formDefinition 中有且仅有一个对应项。注意,你提供的示例数据格式为:
[{"name": "Alice"}, {"sex": "male"}, {"occupation": "Engineer"}]
这是一种“扁平化键值对数组”,每个子对象只含一个字段。因此校验时需先合并或逐个提取键,再统一比对。
以下是推荐的健壮实现(支持 PHP 7.4+,兼容 stdClass 和关联数组):
public function dataValidator(array $details, array $formDefinition): bool
{
// 提取所有合法字段名(去重)
$allowedKeys = array_column($formDefinition, 'key');
// 遍历提交的每个对象
foreach ($details as $item) {
if (!is_array($item) || count($item) !== 1) {
throw new InvalidArgumentException('Each detail item must be an associative array with exactly one key.');
}
$keys = array_keys($item);
$submittedKey = $keys[0];
// 检查该键是否在 schema 中定义
if (!in_array($submittedKey, $allowedKeys, true)) {
throw new InvalidArgumentException("Invalid field: '{$submittedKey}'. Not defined in form schema.");
}
}
return true;
}
⚠️ 注意事项与增强建议
- 避免松散比较:务必使用 in_array($key, $allowedKeys, true) 的第三个参数 true,防止 '0' 与 0 等类型混淆误判。
- 重复字段拦截:当前结构允许同一字段多次出现(如两个 {"name": "..."}),若业务不允许,可额外用 array_count_values() 统计键频次并限制为 1。
-
类型二次校验(进阶):可在匹配 key 后,进一步校验值类型是否符合 datatype(如 "boolean" 字段值必须为 true/false,而非字符串 "true"):
$schema = array_filter($formDefinition, fn($f) => $f['key'] === $submittedKey)[0] ?? null; if ($schema && $schema['datatype'] === 'boolean' && !is_bool($item[$submittedKey])) { throw new InvalidArgumentException("Field '{$submittedKey}' must be a boolean."); } -
性能优化:若 formDefinition 较大,建议提前构建键索引映射:
$schemaMap = array_column($formDefinition, null, 'key'); // ['name' => [...], 'sex' => [...]]
后续可用 $schemaMap[$submittedKey] ?? null 直接查表,时间复杂度 O(1)。
✅ 使用示例
$formDefinition = [
['key' => 'name', 'datatype' => 'string'],
['key' => 'sex', 'datatype' => 'choice'],
['key' => 'occupation', 'datatype' => 'string'],
['key' => 'isRetired', 'datatype' => 'boolean']
];
$details = [
["name" => "John Doe"],
["sex" => "male"],
["occupation" => "Developer"]
];
try {
$this->dataValidator($details, $formDefinition);
echo "✅ Validation passed.";
} catch (InvalidArgumentException $e) {
echo "❌ " . $e->getMessage();
}
通过此方案,你不仅能阻止非法字段写入数据库,还能为后续类型强校验、默认值填充、前端渲染等环节提供统一 Schema 基础——真正实现「一份 Schema,多端驱动」的动态表单架构。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











