PHP - 检查数组中是否有所需的键并设置可选的键值

时间:2015-02-06 14:39:23

标签: php arrays regex

我正在构建一个获取数据数组的Web API。我想检查此数组是否存在某些键,如果所需的键不存在,则返回false,如果不存在可选键,则在数组中设置该键值对。

混淆来自我的输入数组,可能有数组作为值。例如,假设我输入一个这样的数组:

$input_array = array(
    ’name’ => ‘Adam’,
    ‘address’ => array(
        ‘number’ => 12,
        ‘street’ => ‘My Street’
    )
);

我需要密钥:

$required_keys = array(
    ‘name’,
    ‘address’ => array(
        ‘number’,
        ‘street’
    )
);

可选键:

$optional_keys = array(
    ‘address’ = array(
        ‘postcode’ => ‘WA1'
    )
);

我正在努力测试我的输入数组对这两种类型的测试数组(输入和可选)。

应该发生的事情是: 1)应匹配所有必需的密钥。 2)如果不存在任何可选键,请将它们设置为可选键阵列中的键值对。

我知道(但我没有经验)正则表达式。但是,我知道PHP有一个名为http_build_query(mixed $array);的函数,它接受一个数组并将其转换为URL查询字符串。我的想法是,我可以将输入数组转换为URL字符串,然后将其与我的两个测试数组(必需和可选)组成的正则表达式进行比较。这会有用吗?

如果有人有任何其他想法,我很想知道。 感谢

更新:附加未预期的输出

enter image description here

更新2:附加新输出

enter image description here

更新3:当前代码:

static public function static_test_required_keys(Array $required_keys_array, Array $input_array)
{
    $missing = array();

    foreach ($required_keys_array as $key => $value)
    {
        if (empty($input_array[$key]))
        {
            $missing[] = $key;
        }
        else if (isset($input_array[$key]) && is_array($input_array[$key]))
        {
            $missing = array_merge(Inputter::static_test_required_keys($value, $input_array[$key]), $missing);
        }
    }

    return $missing;
}

更新4:新代码。

tatic public function static_test_required_keys(Array $required_keys_array, Array $input_array)
{
    $missing = array();

    foreach ($required_keys_array as $key => $value)
    {
        if (! isset($input_array[$key]))
        {
            $missing[] = $key;
        }
        else if (isset($input_array[$key]) && is_array($input_array[$key]))
        {
            $missing = array_merge(Inputter::static_test_required_keys($value, $input_array[$key]), $missing);
        }
    }

    return $missing;
}

将代码从isempty()更改为isset()。此页面给出了两者之间的差异。 https://www.virendrachandak.com/techtalk/php-isset-vs-empty-vs-is_null/

5 个答案:

答案 0 :(得分:1)

带有对称输入+所需键的新改进版......

$input_array = array(
    'name' => 'Adam',
    'address' => array(
        'number' => 12,
        'street' => '',
        'phones' => array('home_phone'=>'','fax'=>'555-1212')
    )
);

$required_keys = array(
    'name' => '',
    'address' => array(
        'number' => '',
        'street' => '',
        'phones' => array('home_phone'=>'')
    )
);


function check_required( $input, $required ){
    $missing = array();
    foreach ($required as $k=>$v) {
        if (empty($input[$k])) {
            $missing[] = $k;
        } else if (is_array($v)) {
            $missing = array_merge( check_required( $input[$k], $v ), $missing );
        }
    }
    return $missing;
}

$missing = check_required( $input_array, $required_keys );
if (!empty($missing)) echo 'Please enter your '. implode(', ', $missing);

请在此处查看沙箱... http://sandbox.onlinephpfunctions.com/code/23b908b873b053aefb37770f636b63bba2db960b

答案 1 :(得分:1)

必填字段

您可以使用array_diff检查输入中是否缺少任何必填字段。

可选字段

您可以使用array_merge来设置缺失字段的默认值。

代码

$requiredKeys = [
   'foo',
   'baz',
];

// Take the keys from input
$inputKeys = array_keys($input);

$missingRequiredKeys = array_diff($requiredKeys, $inputKeys)
if (!empty($missingRequiredKeys)) {
    throw new InvalidArgumentException(...);
}

// Setup default values for missing optional keys
$defaultValues = [
   'bar' => 'bas',
];

$result = array_merge($defaultValues, $input);

子数组

对于检查必填字段或设置默认值,重要的是在单个函数中重复上面的代码。

function validateInput(array $input) {
   // Above code

   // Validate field subkeys from a parent required field.
   // or optional field with default value.
   validateFoo($input['foo']);

   // Validate field subkeys from a parent optional field without default value.
   if (array_key_exists('optional_input_without_default', $input)) {
       validateAnotherFooInput($input['optional_input_without_default']);
   }
}

其他选项

您可以通过多种方式使用数组交集,差异和合并来检查Array Book

中的这些函数系列
  

array_diff_assoc - 使用附加索引检查计算数组的差异

     

array_diff_key - 使用用于比较的键计算数组的差异

     

array_diff_uassoc - 使用用户提供的回调函数执行附加索引检查来计算数组的差异

     

array_diff_ukey - 使用键上的回调函数计算数组的差异以进行比较

     

array_diff - 计算数组的差异

     

array_intersect_assoc - 使用附加索引检查计算数组的交集

     

array_intersect_key - 使用密钥计算数组的交集

     

array_intersect_uassoc - 使用附加索引检查计算数组的交集,通过回调函数比较索引

     

array_intersect_ukey - 使用键上的回调函数计算数组的交集以进行比较

     

array_intersect - 计算数组的交集

     

array_udiff_assoc - 使用附加索引检查计算数组的差异,通过回调函数比较数据

     

array_udiff_uassoc - 使用附加索引检查计算数组的差异,通过回调函数比较数据和索引

     

array_udiff - 通过使用回调函数进行数据比较来计算数组的差异

     

array_uintersect_assoc - 使用附加索引检查计算数组的交集,通过回调函数比较数据

     

array_uintersect_uassoc - 使用附加索引检查计算数组的交集,通过回调函数比较数据和索引

     

array_uintersect - 计算数组的交集,通过回调函数比较数据

答案 2 :(得分:0)

// Check if required keys exist
foreach( $required_keys as $req_key => $req_val )
{
    if( !array_key_exists( $req_key, $input_array )
    {
        // if key exists check if it has values set in an array and if 
        // these are also in $input_array
        if( is_array( $req_val ) )
        {
            foreach( $req_val as $inner_req_key )
            {
                if( !isset( $input_array[$req_val][$inner_req_key] )
                {
                    echo "Required key '$req_key' is missing value '$inner_req_key'.";
                }
            }
        }
        echo "Required key '$req_key' is missing.";
    }
}

// Check if optional keys are defined
foreach( $optional_keys as $opt_key => $opt_val )
{
    // Check if key exists, if not copy optional key=>value as whole
    if( !array_key_exists( $opt_key, $input_array )
    {
        $input_array[ $opt_key ] = $opt_val;
    }
    else // key exists
    {
        // if key exists check if it is an array and if optional elements
        // exist, else add them
        if( is_array( $opt_key ) )
        {
            foreach( $opt_key as $inner_opt_key => $inner_opt_val )
            {
                // key is not set, so get from %optional_keys
                if( !isset( $input_array[$opt_key][$inner_opt_key] )
                {
                    $input_array[$opt_key][$inner_opt_key] = $inner_opt_val;
                }
            }
        }
    }
}

很久没有PHP,但也许这会有所帮助。 PS:未测试并添加了一些解释。 HTH

答案 3 :(得分:0)

所以这是我最终的代码,任何人偶然发现这个/想知道我是怎么做到的。随意提交改进意见。

static protected function static_test_required_keys(Array $required_keys_array, Array $input_array, &$error)
{
    //  Loop through each required key and value
    //
    foreach ($required_keys_array as $key => $value)
    {
        //  Check the corresponding value in the input array is not set
        //
        if (! isset($input_array[$key]))
        {
            //  If it isn't set return false with a missing error
            //
            $error = Error::withDomain(INPUTTER_ERROR_DOMAIN,
                                       INPUTTER_ERROR_CODE_KEY_MISSING,
                                       'Missing a required key: ' . $key);

            return false;
        }
        //
        //  Check corresponding value in the input array is set and is an array
        //
        else if (isset($input_array[$key]) && is_array($input_array[$key]))
        {
            //  Recurse the function for sub arrays
            //
            if (! Inputter::static_test_required_keys($value, $input_array[$key], $error))
            {
                //  If we return false from this one, we've found at least one error and don't need to continue
                //
                return false;
            }
        }
    }

    //  If we get here then it must be valid
    //
    return true;
}

static protected function static_set_optional_key_values(Array $optional_dictionary, Array &$input_array, &$error)
{
    //  Loop through each optional key/value
    //
    foreach ($optional_dictionary as $key => $value)
    {
        //  Check the key doesn't exist in the input array OR the corresponding value in the input array is not set
        //
        if (! array_key_exists($key, $input_array) || ! isset($input_array[$key]))
        {
            //  Set the new key/value
            //              
            $input_array[$key] = $value;
        }
        //
        //  Check corresponding value in the input array is set and is an array
        //
        else if (isset($input_array[$key]) && is_array($input_array[$key]))
        {
            //  Recurse the function for sub arrays
            //
            Inputter::static_set_optional_key_values($value, $input_array[$key], $error);
        }
    }
}

答案 4 :(得分:0)

我不知道您要在哪里运行此代码。

如果它在浏览器中或在Javascript中。

由于我有疑问,我已经做到了这一点:

function array_extend() {

    //Detects if we are running in Javascript or PHP
    //In PHP, this will be false because PHP only parses
    //escape sequences in double-quoted strings (except the sequence \')
    $javascript = '\0' == "\0";

    //PHP arrays support 'key=>value' pairs, JS arrays don't.
    $result = $javascript ? new Object() : array();

    $arguments = $javascript? arguments : func_get_args();

    $get_keys = function($elem){
        if('\0' == "\0")//PHP complains if I use the var $javascript
        {
            $object = Object;
            return $object['keys']($elem); //PHP doesn't like the Object.keys syntax
        }
        else
        {
            return array_keys($elem);
        }
    };


    for($j = 0, $length_args = $javascript? $arguments['length']: count($arguments); $j < $length_args; $j++)
    {
        $keys = $get_keys( $arguments[$j] );

        for($i = 0, $length_keys = $javascript? $keys['length']: count($keys); $i < $length_keys; $i++)
        {
            $result[$keys[$i]] = $arguments[$j][$keys[$i]];
        }
    }

    return $result;
}

它在PHP和Javascript中运行。

目前,我在另一个网站上有一个已打开的问题,展示了该功能。

您可以继续https://codereview.stackexchange.com/questions/79804/polyglot-array-extend-function-for-javascript-and-php进行检查。