How to search by key=>value in a multidimensional array in PHP
Code:
function search($array, $key, $value){ $results = array(); if (is_array($array)) { if (isset($array[$key]) && $array[$key] == $value) { $results[] = $array; } foreach ($array as $subarray) { $results = array_merge($results, search($subarray, $key, $value)); } } return $results;}$arr = array(0 => array(id=>1,name=>"cat 1"), 1 => array(id=>2,name=>"cat 2"), 2 => array(id=>3,name=>"cat 1"));print_r(search($arr, 'name', 'cat 1'));
Output:
Array( [0] => Array ( [id] => 1 [name] => cat 1 ) [1] => Array ( [id] => 3 [name] => cat 1 ))
If efficiency is important you could write it so all the recursive calls store their results in the same temporary $results
array rather than merging arrays together, like so:
function search($array, $key, $value){ $results = array(); search_r($array, $key, $value, $results); return $results;}function search_r($array, $key, $value, &$results){ if (!is_array($array)) { return; } if (isset($array[$key]) && $array[$key] == $value) { $results[] = $array; } foreach ($array as $subarray) { search_r($subarray, $key, $value, $results); }}
The key there is that search_r
takes its fourth parameter by reference rather than by value; the ampersand &
is crucial.
FYI: If you have an older version of PHP then you have to specify the pass-by-reference part in the call to search_r
rather than in its declaration. That is, the last line becomes search_r($subarray, $key, $value, &$results)
.
How about the SPL version instead? It'll save you some typing:
// I changed your input example to make it harder and// to show it works at lower depths:$arr = array(0 => array('id'=>1,'name'=>"cat 1"), 1 => array(array('id'=>3,'name'=>"cat 1")), 2 => array('id'=>2,'name'=>"cat 2"));//here's the code: $arrIt = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); foreach ($arrIt as $sub) { $subArray = $arrIt->getSubIterator(); if ($subArray['name'] === 'cat 1') { $outputArray[] = iterator_to_array($subArray); }}
What's great is that basically the same code will iterate through a directory for you, by using a RecursiveDirectoryIterator instead of a RecursiveArrayIterator. SPL is the roxor.
The only bummer about SPL is that it's badly documented on the web. But several PHP books go into some useful detail, particularly Pro PHP; and you can probably google for more info, too.
<?php$arr = array(0 => array("id"=>1,"name"=>"cat 1"), 1 => array("id"=>2,"name"=>"cat 2"), 2 => array("id"=>3,"name"=>"cat 1"));$arr = array_filter($arr, function($ar) { return ($ar['name'] == 'cat 1'); //return ($ar['name'] == 'cat 1' AND $ar['id'] == '3');// you can add multiple conditions});echo "<pre>";print_r($arr);?>