26

I have a multidimensional array e.g. (this can be many levels deep):

$array = Array ( 
    [21] => Array ( ) 
    [24] => Array ( 
        [22] => Array ( ) 
        [25] => Array ( 
            [26] => Array ( ) 
        ) 
    ) 
) 

I am trying to loop through it to see if a certain key exists:

$keySearch = 22; // key searching for

function findKey($array, $keySearch) {
    foreach ($array as $item){
        if (isset($item[$keySearch]) && false === findKey($item[$keySearch], $item)){
            echo 'yes, it exists';
        }
    }
}

findKey($array, $keySearch);

But it finds nothing. Is there an error in the loop?

StudioTime
  • 20,816
  • 34
  • 110
  • 202

8 Answers8

50

array_key_exists() is helpful.

Then something like this:

function multiKeyExists(array $arr, $key) {

    // is in base array?
    if (array_key_exists($key, $arr)) {
        return true;
    }

    // check arrays contained in this array
    foreach ($arr as $element) {
        if (is_array($element)) {
            if (multiKeyExists($element, $key)) {
                return true;
            }
        }

    }

    return false;
}

Working example: http://codepad.org/GU0qG5su

Tim
  • 6,111
  • 2
  • 37
  • 48
43

I played with your code to get it working :

function findKey($array, $keySearch)
{
    foreach ($array as $key => $item) {
        if ($key == $keySearch) {
            echo 'yes, it exists';
            return true;
        } elseif (is_array($item) && findKey($item, $keySearch)) {
            return true;
        }
    }
    return false;
}
mickmackusa
  • 37,596
  • 11
  • 75
  • 105
Alexandre Nucera
  • 2,133
  • 2
  • 21
  • 34
  • 1
    Shouldnt: "if (isset( $array[$key] ) )" be: "if( is_array( $array[$key] ) )"? Obviously the $key is set in $array because the foreach is looping that array. – David Lawrence Jul 05 '15 at 02:28
  • `if (is_array($item)) findKey($item, $keySearch);` - the return value of this call is lost. – VolkerK Sep 28 '15 at 15:45
  • 1
    I've edited to condense the if block. If this was my code, I'd rather rather use a single `if` with `||`. *using parentheses as logic requires. – mickmackusa Jan 13 '18 at 05:19
  • thanks for this...btw, from my testing, it's better to set the === operator for this to work properly. – Steven Yip Jul 23 '21 at 08:35
  • To make it more complete, I would suggest also checking if $item isn't empty. This can avoid some problems down the road. – tibelchior Aug 27 '21 at 13:38
10

Here is a one line solution:

echo strpos(json_encode($array), $key) > 0 ? "found" : "not found";

This converts the array to a string containing the JSON equivalent, then it uses that string as the haystack argument of the strpos() function and it uses $key as the needle argument ($key is the value to find in the JSON string).

It can be helpful to do this to see the converted string: echo json_encode($array);

Be sure to enclose the needle argument in single quotes then double quotes because the name portion of the name/value pair in the JSON string will appear with double quotes around it. For instance, if looking for 22 in the array below then $key = '"22"' will give the correct result of not found in this array:

$array =
Array ( 
        21 => Array ( ), 
        24 => 
        Array ( 
            522 => Array ( ),
            25 =>
                Array ( 
                26 => Array ( ) 
            )
        )
    );

However, if the single quotes are left off, as in $key = "22" then an incorrect result of found will result for the array above.

EDIT: A further improvement would be to search for $key = '"22":'; just incase a value of "22" exists in the array. ie. 27 => "22" In addition, this approach is not bullet proof. An incorrect found could result if any of the array's values contain the string '"22":'

knot22
  • 2,331
  • 2
  • 25
  • 44
  • 1
    I would refuse a solution that works in the simplified case, but not when "special circumstances" occurs. If the values of the array may not contain all arbitrary values cause that might disturb your algorithm, the algorithm is miscrafted – Nico Haase Sep 14 '18 at 06:00
  • Not agreed !! Because it will also return "found" if a value equals the searched key. – Jerry Jun 23 '20 at 17:37
5
function findKey($array, $keySearch)
{
    // check if it's even an array
    if (!is_array($array)) return false;

    // key exists
    if (array_key_exists($keySearch, $array)) return true;

    // key isn't in this array, go deeper
    foreach($array as $key => $val)
    {
        // return true if it's found
        if (findKey($val, $keySearch)) return true;
    }

    return false;
}

// test
$array = Array ( 
    21 => Array ( 24 => 'ok' ),
    24 => Array ( 
        22 => Array ( 29 => 'ok' ),
        25 => Array ( 
            26 => Array ( 32 => 'ok' ) 
        )
    )
);

$findKeys = Array(21, 22, 23, 24, 25, 26, 27, 28, 29, 30);
foreach ($findKeys as $key)
{
    echo (findKey($array, $key)) ? 'found ' : 'not found ';
    echo $key.'<br>';
}
minboost
  • 2,555
  • 1
  • 14
  • 15
3

returns false if doesn't exists, returns the first instance if does;

function searchArray( array $array, $search )
{
    while( $array ) {
        if( isset( $array[ $search ] ) ) return $array[ $search ];
            $segment = array_shift( $array );
            if( is_array( $segment ) ) {
                if( $return = searchArray( $segment, $search ) ) return $return;
            }
        }
    }
    return false;
}
Luke Snowden
  • 3,720
  • 2
  • 33
  • 66
2

For sure some errors, is this roughly what you are after? (Untested code):

$keySearch=22; // key seraching for

function findKey($array, $keySearch) 
{ 
    // check whether input is an array
    if(is_array($array)
    {
       foreach ($array as $item)
       {
         if (isset($item[$keySearch]) || findKey($item, $keysearch) === true)
          {
            echo 'yes, it exists';
            return true;
          }
       }
    }
}
Pradeep
  • 9,481
  • 13
  • 27
  • 34
Jelle Ferwerda
  • 1,269
  • 1
  • 7
  • 13
0

Here is one solution that finds and return the value of the key in any dimension array..

function findValByKey($arr , $keySearch){
    $out = null;
    if (is_array($arr)){
        if (array_key_exists($keySearch, $arr)){
            $out = $arr[$keySearch];
        }else{
            foreach ($arr as $key => $value){
                if ($out = self::findValByKey($value, $keySearch)){
                    break;
                }
            }
        }
    }
    return $out;
}
0
function arrayKeyExsits($array, $keyPath): bool {
    $keys = explode('=>', $keyPath);
    if (count($keys) === 1) {
        return array_key_exists($keyPath, $array);
    } else {
        $key = array_shift($keys);
        if (array_key_exists($key, $array)) {
            return arrayKeyExsits($array[$key], implode('=>', $keys));
        } else {
            return false;
        }
    }
}
$array = [
    'level1' => [
        'level2' => [
            'level3' => [
             ]
        ]
    ]
];

var_dump(arrayKeyExists($array, 'level1')) // true
var_dump(arrayKeyExists($array, 'level1=>level2')) // true
var_dump(arrayKeyExists($array, 'level1=>level2=>level3')) // true

var_dump(arrayKeyExists($array, 'foo')) // false
var_dump(arrayKeyExists($array, 'level1=>foo=>level3')) // false

d4nni5
  • 1
  • 1