6
$temp = array();
function show_keys($ar)
{
    foreach ($ar as $k => $v )
    {
        $temp[] = $k;
        if (is_array($ar[$k]))
        {
            show_keys ($ar[$k]);
        }
    }

    return $temp;
}

I tried using that function but it still only returns the first key.

HyderA
  • 20,651
  • 42
  • 112
  • 180
  • This recursion is infinite in many cases. – Svisstack Oct 06 '10 at 13:29
  • 2
    A note on style: Don't call variables `temp` or `tmp`, **especially** in the global namespace, that leads to confusion. Names should be descriptive; call it `keys`, since that's what it contains. – user229044 Oct 06 '10 at 13:31

9 Answers9

11

Using SPL, looping over the keys is quite easy (store them in another array if you wish):

<?php
$arr = array_fill(0,8,range(0,3));
var_dump($arr);
foreach( new RecursiveIteratorIterator(
    new RecursiveArrayIterator($arr),
    RecursiveIteratorIterator::SELF_FIRST)
  as $key => $value){
        var_dump($key);
}
?>
Wrikken
  • 69,272
  • 8
  • 97
  • 136
6

I see a lot of overly complicated solutions here....

function array_keys_r($array) {
  $keys = array_keys($array);

  foreach ($array as $i)
    if (is_array($i))
      $keys = array_merge($keys, array_keys_r($i));

  return $keys;
}
user229044
  • 232,980
  • 40
  • 330
  • 338
5

The main problem is that you are throwing away the results of the recursive show_keys() calls. You don't do anything with the return value.

Comments are inline.

function show_keys($ar)
{
    // Create new temp array inside function so each recursive call gets
    // a separate instance.
    $temp = array();

    foreach ($ar as $k => $v )
    {
        $temp[] = $k;

        // Use $v instead of $ar[$k].
        if (is_array($v))
        {
            // Combine results of recursive show_keys with $temp.
            $temp = array_merge($temp, show_keys($v));
        }
    }

    return $temp;
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
2

This might do the trick?

You'd have to either bring in $temp as a global, or pick up the returned value from each recursion. And we'd want to avoid global variables, so we merge the values from each recursion call with previous gathered values.

function show_keys($ar)
{
    $temp = array();
    foreach ($ar as $k => $v )
    {
        $temp[] = $k;
        if (is_array($ar[$k]))
        {
            $temp = array_merge(show_keys ($ar[$k]), $temp);
        }
    }

    return $temp;
}
Alexander Sagen
  • 4,028
  • 1
  • 18
  • 15
2

As a supplement for other solutions there is possibility to return flattened array as a result but still keep the information about the tree. We can concatenate nested keys with parent. It could be useful for diffing with other arrays as you are distinguishing between same child keys but different parents

function array_keys_flatten_recursive($array, $parentKey = "") {
    $keys = array_keys($array);
    foreach ($array as $parentKey => $i)
      if (is_array($i)) {
        $nestedKeys = array_keys_flatten_recursive($i, $parentKey);
        foreach($nestedKeys as $index => $key) {
            $nestedKeys[$index] = $parentKey . "." . $key;
        }
        $keys = array_merge($keys, $nestedKeys);
      }
    return $keys;
}

Example:

$array = array(
    "one" => array(
        "one" => "lorem"
    ),
    "two" => array(
        "one" => "lorem"
    )
);


// result : array("one", "two", "one.one", "two.one")
M Tomczynski
  • 15,099
  • 1
  • 15
  • 25
1

The question is ambiguous because you did not specify your input and expected output.

Consider this example array:

$array = [
    'first' => [
        'second' => [
            'third' => 'three',
        ],
        'deuxième' => 'two',
    ],
];

All of the other solutions so far provide a flattened one-dimensional array list of keys.

$keys = [
    'first',
    'second',
    'third',
    'deuxième',
];

However, I had a need for an array_keys_recursive function that would preserve the hierarchy.

$keys = [
    'first' => [
        'second' => [
            'third',
        ],
        'deuxième',
    ],
];

For anyone else searching for a similar need, here's my solution:

function array_keys_recursive(array $array) : array
{
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $index[$key] = array_keys_recursive($value);
        } else {
            $index []= $key;
        }
    }

    return $index ?? [];
}
Jeff Puckett
  • 37,464
  • 17
  • 118
  • 167
0

Your array $temp is global. To make is accessible in the function you need :

global $temp;

at the start of the function.

Currently every invocation of the function is creating a new array with the name $temp and when you finally return from the function to its caller, the $temp you created in your first call is being returned, which has only the keys of your first level.

Note that using global variables is not good programming. You need to pass your array as argument to your recursive calls and modify the passed array by adding keys found in each iterations as Alexander and John have done.

codaddict
  • 445,704
  • 82
  • 492
  • 529
0

Ofcause this function is infinite. But my task is to help you)

function show_keys($ar, $temp = array())
{    
    if (!empty($ar)) {
    foreach ($ar as $k => $v )
    {
        $temp[] = $k;
        if (is_array($ar[$k]))
        {
            $temp += show_keys($ar[$k], $temp);
        }
    }
    }

    return $temp;
}
Alex Pliutau
  • 21,392
  • 27
  • 113
  • 143
0
    /**
     * @param array $array
     * @param string $devider
     * @return array
     */
    static public function arrayKeysRecursive(array $array, $devider='.'){
        $arrayKeys = [];
        foreach( $array as $key=>$value ){
            if( is_array($value) ){
                $rekusiveKeys = self::arrayKeysRecursive($value, $devider);
                foreach( $rekusiveKeys as $rekursiveKey ){
                    $arrayKeys[] = $key.$devider.$rekursiveKey;
                }
            }else{
                $arrayKeys[] = $key;
            }
        }
        return $arrayKeys;
    }

use it

arrayKeysRecursive(['one'=>['two'=>2, 'three'=>['four'=>4]]])

returns

['one.two', 'one.three.four']
Grain
  • 553
  • 4
  • 5