我有一个多维数组,需要验证数组是否包含正确图层上的必填字段。
有没有很好的方法来实现这一目标?输入可以是数组或JSON。
到目前为止我的approche:
让我们假设输入数组如下:
Array (
[key] => key string
[sub] => Array (
[0] => Array (
[id] => 123456
[src] => source string
[src_ids] => Array (
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
[data] => Array (
[a_data] => a string
[b_data] => b string
[c_data] => c string
)
)
[1] => Array (
[id] => 557799
[src] => source string
[src_ids] => Array (
[0] => 1
[1] => 2
)
[data] => Array (
[a_data] => a string
[b_data] => b string
[c_data] => c string
)
)
)
)
强制值为:
sub, id, src, src_ids, data, a_data
可选值是其他所有内容:
key, 0 (of sub), 0-3 (of src_ids), b_data, c_data
我想有一个函数可以根据必填字段检查任何输入数组。 我的想法是将强制值创建为基于以下层的数组:
$mandatory = array(
1 => array( 'sub' ),
3 => array( 'id', 'src', 'src_id', 'data' ),
4 => array( 'a_data' )
);
关键是图层的深度,数组值是该图层允许的关键名称。
现在我尝试抓取输入数组,并根据深度检查密钥是否在强制字段中:
/**
*
* @param array $i input
* @param array $m mandatory
* @param integer $d depth
* @return boolean
*/
function validate( $i, $m, $d=1 ) {
foreach( $i as $k => $v ) {
if( isset($m[$d]) ) {
if( !in_array($k, $m[$d]) ) {
return false;
} else {
if( is_array($v) ) {
$d++;
validate($v, $m, $d );
}
}
} else {
if( is_array($v) ) {
$d++;
validate($v, $m, $d );
}
}
}
return true;
}
但这会导致两个主要问题:
我也尝试使用比较数组,但由于多个条目,我无法将所有条目与强制数组进行比较。
非常感谢任何帮助,建议或解决方案。
由于
答案 0 :(得分:1)
这是否符合您的要求?
必填字段结构:
$required = array(
'sub' => array(
array(
'id' => '',
'src' => '',
'src_ids' => '',
'data' => array(
'a_data' => '',
),
),
),
);
基本上只是模仿输入数组的结构。字段名称是键;必需的子字段是后代。如果它是与sub[0]
和sub[1]
一样的列表,则保留键数字/未命名,它将检查列表中每个项目的结构。
递归验证功能:
function checkRequired($data, $req)
{
// no more required fields
if (empty($req))
return true;
// no more data fields; obviously lacks required field(s)
if (empty($data))
return false;
foreach ($req as $name => $subtree) {
// unnamed; it's a list
if (is_numeric($name)) {
foreach ($data as $dataitem) {
if (checkRequired($dataitem, $subtree) == false)
return false;
}
} else {
// required field doesn't exist
if (!isset($data[$name]))
return false;
// fine so far; down we go
if (!empty($subtree)
&& checkRequired($data[$name], $subtree) == false
) {
return false;
}
}
}
return true;
}
我可能会在某个地方蠢蠢欲动,但希望你可以将它改编成有用的东西。这是你可以试验的working example of this。
答案 1 :(得分:1)
如果您按照描述定义$input
和$mandatory
,其余代码如下所示:
$values[1] = $input;
$layer = 1;
$found_layer = true;
while($found_layer)
{
$found_layer = false;
foreach($values[$layer] as $li=>$le)
{
if(is_array($le))
{
$found_layer = true;
if(!isset($values[$layer+1])) $values[$layer+1] = array();
$values[$layer+1] = array_merge($le, $values[$layer+1]);
$values[$layer][$li] = 'array';
}
}
$layer++;
}
$not_found = $mandatory;
foreach($not_found as $layer=>$keys_to_match)
{
foreach($values[$layer] as $key=>$value)
{
foreach($keys_to_match as $ktmi=>$ktm)
{
if($ktm==$key) unset($not_found[$layer][$ktmi]);
}
}
if(!count($not_found[$layer])) unset($not_found[$layer]);
else $not_found[$layer] = array_values($not_found[$layer]);
}
然后代码会生成$not_found
,如下所示:
Array
(
[3] => Array
(
[0] => src_id
)
)
这意味着,在输入的第三级(“层”)上没有使用键“src_id”的元素,根据$mandatory
这是必需的。如果找到所有必需元素,则$not_found
将为空。请注意,'src_id'
中有$mandatory
,但$input
显然只有一个键'src_ids'
。
我避免使用递归来提高性能。