PHP 检查数组是否包含白名单以外的任何键

PHP check if array contains any key other than some whitelisted

我想检查全局 GET 数组的所有键并做一些事情,如果它包含键,而不是数组中一些列入白名单的键。

假设当前 url 是:

.../index.php?randomekey1=valueX&randomkey2=valueY&acceptedkey1=valueZ&randomkey3=valueA&acceptedkey2=valueB

只是为了更好的可视化: 这些 GET 参数都在全局 GET 变量中可用,看起来像这样:

$GET = array(
    "randomekey1" => "valueX",
    "randomkey2" => "valueY",
    "acceptedkey1" => "valueZ",
    "randomkey3" => "valueA",
    "acceptedkey2" => "valueB"
);

我接受并希望通过的密钥,我也放入了一个数组:

$whitelist = array(
    "acceptedkey1",
    "acceptedkey2",
    "acceptedkey3",
);

现在我想检查 $GET 是否包含白名单以外的任何密钥。所以在上面的 URL 示例中,它应该 return "true",因为 $GET 数组中的键不在白名单中。

不仅存在这样一个未知(none白名单)密钥应该触发一个真实的,但也请它为空!


另一个例子如下 url:

.../index.php?acceptedkey1=valueZ&acceptedkey3=valueB

这应该 return 错误,因为除了白名单中的密钥之外没有找到其他密钥。

不幸的是,我无法找到符合这些要求的 in_array 函数或 array_search 的任何修改,因为据我所知,这些函数只是在寻找特定的东西,而在我的要求中,我也在寻找特定的东西(白名单密钥),但同时我必须检查是否存在一些未知密钥。

谢谢。

PHP 中的所有内容不必都是 "lets find function that does exactly what I'm looking for"。只需做一个简单的 foreach 循环,它就可以完成您要查找的内容:

function clear_filter() {
    $whitelist = array( "project", "table_name", "filterDates", );
    foreach ($_GET as $gkey => $gval) {
        if (!in_array($gkey, $whitelist)) {
            return false;
        }
    }
    return true;
}

你也可以写的简单一点,一个foreach循环如下:

function isValid() {
    // Copy the array
    $temp = $_GET;

    // Loop through the array, and remove any whitelisted elements
    foreach ($whitelist as $wkey) {
        unset($temp[$wkey]);
    }
    // If count($temp) > 0, there are non whitelisted entries in the array.
    return count($temp) === 0;
}

您似乎想判断一个数组是否包含白名单中不存在的键。
找到数组之间差异的一种方法是使用 array_diff():

array_diff ( array $array1 , array $array2 [, array $... ] ) : array
Returns an array containing all the entries from array1 that are not present in any of the other arrays.

因此,它可以用于 return URL 中不存在于白名单中的所有密钥:

$extrasExist = !empty( array_diff( array_keys($GET), $whitelist ) );
var_dump($extrasExist);

这是一个演示:

$get1 = array(
    "randomekey1" => "valueX",
    "randomkey2" => "valueY",
    "acceptedkey1" => "valueZ",
    "randomkey3" => "valueA",
    "acceptedkey2" => "valueB"
);

$get2 = array(
    "acceptedkey1" => "valueZ",
    "acceptedkey2" => "valueB"
);

$whitelist = array(
    "acceptedkey1",
    "acceptedkey2",
    "acceptedkey3"
);

$extrasExist = !empty(array_diff(array_keys($get1),$whitelist));
var_dump($extrasExist);

$extrasExist = !empty(array_diff(array_keys($get2),$whitelist));
var_dump($extrasExist);

bool(true)
bool(false)

您可以使用以下功能。

$check = checkWhitliest( $_GET, $whitelist ) );
var_dump ($check );

你可以调用上面的函数

function checkWhitliest( $array, $whitelist ) {

    $allKeys = array_keys ( $array); //Get all Keys from the array.
    $diff = array_diff( $allKeys, $whitelist); //Get the values which are not in whitelist.
    if( count ( $diff ) > 0 ) {     //If the count is greater than 0, then there are certain extra kesy in $_GET
        return true;
    }
    return false;

}

对于此任务,我只推荐两种技术,并且两者都出于性能原因进行了关键比较。使用 array_diff()in_array() 总是比 array_diff_key()isset() 慢,因为 PHP 将数组视为哈希映射。

如果你不介意迭代整个$GET数组(因为它的数据比较小),那么你可以简洁地翻转白名单数组并检查是否有任何关键差异。

var_export(
    (bool)array_diff_key($GET, array_flip($whitelist))
);

如果性能比代码简洁更重要,那么您应该设计一种技术,在遇到 non-whitelisted 键时立即使用条件 breakreturn -- 这避免在结果确定后进行无意义的迭代。

$hasNotWhitelisted = false;
$lookup = array_flip($whitelist);
foreach ($GET as $key => $value) {
    if (isset($lookup[$key])) {
        $hasNotWhitelisted = true;
        break;
    }
}
var_export($hasNotWhitelisted);

或者

function hasNotWhitelisted($array, $whitelist): bool {
    $lookup = array_flip($whitelist);
    foreach ($array as $key => $value) {
        if (isset($lookup[$key])) {
            return true;
        }
    }
    return false;
}
var_export(hasNotWhitelisted($GET, $whitelist));

上述所有技术都为示例数据提供了 true 结果。 Demo of all three snippets.