I'm trying to iterate over every element of an array recursively to get the values where the key is equal to page_id
or content_id
.
The problem is that in callback function, in a switch statement I get completely weird behaviour, where case is matched but value is different.
This was driving me nuts for quite some time. I even tried to use strict comparison like if($key === 'component_id') print $key; die();
. I'm expecting to get 'component_id' as the output but get '0'. How is that possible?
While writing this question, I also noticed this happens when there is indexed array at some point, but I'm not sure if that is the problem.
Here is an example code from full solution.
Thanks.
<?php
class Arr
{
public static function map($array, $callback, $recursive = false)
{
foreach ($array as $key => $value) {
$array[$key] = $callback($key, $value);
if($recursive && is_array($array[$key])) {
$array[$key] = static::map($array[$key], $callback, true);
}
}
return $array;
}
}
$data = [
'id' => 12,
'data' => [
'terms' => [
[
'href' => null,
'icon' => 'lock',
'target' => '_blank'
],
[
'href' => 'http://example.com',
'icon' => 'lock',
'target' => '_blank'
]
],
'license_info' => [
'content_id' => 6
]
]
];
$contents = [];
$pages = [];
Arr::map($data, function ($key, $value) use (&$contents, &$pages) {
switch ($key) {
case 'content_id':
print $key; die(); // 0 ?????
$contents[] = $value;
break;
case 'page_id':
$pages[] = $value;
break;
}
return $value;
}, true);
I expected the output to be component_id
, but I got 0
.
Also I know I could use array_walk
or array_walk_recursive
, but I prefer this approach as it's more elegant and readable in my opinion.
Your code looks ok. The problem is that 0 == 'content_id'
is True. And switch
in PHP is using loose (==
) comparison. And because in terms
you have two values without string keys, they are automatically indexed starting at 0.
So what you get is not when your function finds
'content_id' => 6
but when it finds
/* 0 => */
[
'href' => null,
'icon' => 'lock',
'target' => '_blank'
],
EDIT:
Bottom line is - you have to use if
with strict comparison ===
in this case (or use string keys everywhere).