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;
}
1

2 Answers 2

1
+50

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

Sign up to request clarification or add additional context in comments.

Comments

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.

2 Comments

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".
Fair point. I'd not considered that. I'll take another look and see if I can come up with a better solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.