1

I want to search values in array by key, but I am having trouble when those keys value are an array, I have the following code:

$key_to_search = "sizes";
$result   = [];
$array =  [
    "color" => "red",
    "subcolor" => "green",
    "sizes" => [
        "depth_mm" => 40.5,
        "width_mm" => 300,
        "height_mm" => 2
    ],
    "launch_date" => "2023-01-01"
];

$iterator = new \RecursiveIteratorIterator(
    new \RecursiveArrayIterator(
        $array
    )
); 

foreach($iterator as $key=>$value)
{
   if($key_to_search==$key && $value!=='')
   {
      $result[] = $value;
   }
}

var_dump($result);

The key to search is on $key_to_search variable, if I use other one which does not have an array as value its finding correctly the values, but when the value is an array it just ignored.

Expected result for search of "sizes" would be:

[
   "depth_mm" => 40.5,
   "width_mm" => 300,
   "height_mm" => 2
]

There's a working example using the classic way without RecursiveIteratorIterator:

public function searchPropertyValuesByKey($key_to_search, $array_to_search = null) {
    if($array_to_search == null) {
       $array_to_search = [
        "color" => "red",
        "subcolor" => "green",
        "sizes" => [
            "depth_mm" => 40.5,
            "width_mm" => 300,
            "height_mm" => 2
        ],
        "launch_date" => "2023-01-01"
      ];
    }

    $result = [];
    foreach($array_to_search as $key=>$value)
    {
        if($key_to_search==$key && $value!=='')
        {
            $result[] = $value;
        }
        if(is_array($value)){
            $callback_result = $this->searchPropertyValuesByKey($key_to_search, $value);
            if($callback_result !== null) {
                $result[] = $callback_result;
            }
        }
    }
    if(count($result) == 1)
        return $result[0];
    else if(count($result) > 1)
        throw new \Exception("Property '".$key_to_search."' is found multiple times! (".count($result).") ".json_encode($result).", in product_id: ".$this->id." >> ".json_encode($this->propierties)."");
    else
        return null;
}
Olivier
  • 13,283
  • 1
  • 8
  • 24
Troyer
  • 6,765
  • 3
  • 34
  • 62
  • Duplicate of https://stackoverflow.com/questions/35755683/php-recursiveiteratoriterator-not-outputting-all-keys. – Nigel Ren Mar 17 '23 at 20:00

2 Answers2

1

The constructor of RecursiveIteratorIterator has three parameters: a Traversable (which you correctly specified), a $mode, which defaults to RecursiveIteratorIterator::LEAVES_ONLY (that's the problem) and $flags. So, in order to consider non-leaf items, you will need to specify a different value for your second parameter. I have tried your example with RecursiveIteratorIterator::SELF_FIRST and it worked.

Code:

$key_to_search = "sizes";
$result   = [];
$array =  [
    "color" => "red",
    "subcolor" => "green",
    "sizes" => [
        "depth_mm" => 40.5,
        "width_mm" => 300,
        "height_mm" => 2
    ],
    "launch_date" => "2023-01-01"
];

$iterator = new \RecursiveIteratorIterator(
    new \RecursiveArrayIterator(
        $array
    ), RecursiveIteratorIterator::SELF_FIRST
); 

foreach($iterator as $key=>$value)
{
   if($key_to_search==$key && $value!=='')
   {
      $result[] = $value;
   }
}

var_dump($result);

Result:

enter image description here

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
0

If you change the definition of $iterator to the following, it works as you've stated:

$iterator = new \RecursiveArrayIterator($data);

I don't believe that the RecursiveIteratorIterator is required.

Matthew Setter
  • 2,397
  • 1
  • 19
  • 18
  • The problem then is if I have the key multiple times it returns only the last one. Plus it does not go deep in arrays, for example if you search for "depth_mm". – Troyer Mar 15 '23 at 07:35
  • Fair point. I'd not considered that. I'll take another look and see if I can come up with a better solution. – Matthew Setter Mar 16 '23 at 09:33