当使用数组做复杂的事情时,我很快就会感到困惑。
我正在尝试创建一个函数arrayStructure($candidate, $structure)
:
candidate
数组是否包含给定的structure
。我有什么:
// The array that will be validated
$candidate = [
'persons' => [
'john',
'amanda'
],
'animals' => [
'dog',
'monkey'
],
'aliens' => 'scary_one'
];
// The structure the candidate has to contain
$structure = ['persons', 'animals' => ['species'] ];
arrayStructure($candidate, $structure);
这应返回 false ,因为$candidate['animals']
没有密钥species
。
现在,如果我们要向$candidate['animals']
添加一个物种数组,就像这样:
$candidate = [
'persons' => [
'john',
'amanda'
],
'animals' => [
'species' => [],
'dog',
'monkey'
],
'aliens' => 'scary_one'
];
// The structure the candidate has to contain
$structure = ['persons', 'animals' => ['species'] ];
arrayStructure($candidate, $structure);
这将返回 true ,因为$ candidate 包含 $structure
中给出的结构。
请注意以下事项:
persons
不是键,而是值,但它会查找persons
键候选人。 species
也是如此。arrayStructure
检查候选者是否包含键,这就是为什么它会在第二个例子中返回true,即使候选者包含“外星人”而结构不包含“外星人”。 有没有人知道如何才能做到这一点?
Laravel在PHPUnit帮助函数assertJsonStructure
中执行与JSON结构类似的操作:
public function assertJsonStructure(array $structure = null, $responseData = null)
{
if (is_null($structure)) {
return $this->assertJson();
}
if (is_null($responseData)) {
$responseData = $this->decodeResponseJson();
}
foreach ($structure as $key => $value) {
if (is_array($value) && $key === '*') {
PHPUnit::assertInternalType('array', $responseData);
foreach ($responseData as $responseDataItem) {
$this->assertJsonStructure($structure['*'], $responseDataItem);
}
} elseif (is_array($value)) {
PHPUnit::assertArrayHasKey($key, $responseData);
$this->assertJsonStructure($structure[$key], $responseData[$key]);
} else {
PHPUnit::assertArrayHasKey($value, $responseData);
}
}
return $this;
}
使数组变得更简单(当我使用上面的示例运行PHPUNIT测试时,这项工作):
public function assertArrayStructure(array $structure = null, array $array)
{
foreach ($structure as $key => $value) {
if (is_array($value)) {
PHPUnit::assertArrayHasKey($key, $array);
$this->assertArrayStructure($structure[$key], $array[$key]);
} else {
PHPUnit::assertArrayHasKey($value, $array);
}
}
return $this;
}
这也是我在自己的实验中所拥有的,除了我无法让数组有工作的关键(PHPUnit做了一些额外的事情,我想弄清楚)。
答案 0 :(得分:0)
function arrayStructure(array $structure = null, array $array, &$errors = [])
{
foreach ($structure as $key => $value) {
if (is_array($value)) {
if (!array_key_exists($key, $array)) $errors[] = false;
arrayStructure($structure[$key], $array[$key], $errors);
} else {
if (!array_key_exists($value, $array)) $errors[] = false;
}
}
return empty($errors);
}
如果密钥不存在,我们会不断添加$errors
数组,这意味着如果错误不为空,则候选人没有结构。这个成功了:
persons is checked in: {"persons":["john","amanda"],"animals":{"species":[],"0":"dog","1":"monkey"},"other":"value"}
animals is checked in: {"persons":["john","amanda"],"animals":{"species":[],"0":"dog","1":"monkey"},"other":"value"}
species is checked in: {"species":[],"0":"dog","1":"monkey"}
bool(true)
现在,如果我们移除物种,它将失败:
persons is checked in: {"persons":["john","amanda"],"animals":["dog","monkey"],"other":"value"}
animals is checked in: {"persons":["john","amanda"],"animals":["dog","monkey"],"other":"value"}
species is checked in: ["dog","monkey"]
bool(false)