0

I have a recursive array depth of which is variable, and I want to be able to take a string with a separator and convert that string to an index in that array,

For example

$path = 'level1.level2.level3';

will be converted to get the value 'my data' from the array below

$data['level1']['level2']['level3'] = 'my data';

I thought the quickest way to get this would be to use variable variables, but when I try the following code

$index = "data['level1']['level2']['level3']";

echo $$index;

I get the follwing error

PHP Notice:  Undefined variable: data['level1']['level2']['level3']

All other ways I can think of doing this are very inefficient, could someone please shed some light on this, is it possible using variable variables for arrays in PHP? Any other efficient workaround?

Many thanks.

2
  • what you call "unefficient"? for what reason? Commented Sep 27, 2011 at 13:57
  • I called it "inefficient" because it involved making copies of the arrays inside the recursive array several times if the index is deep, and the array structure is huge. Commented Sep 27, 2011 at 15:08

5 Answers 5

2

You'll have to loop the array, you won't manage to do this using variable variables, as far as I know. This seems to work though:

<?php

function retrieve( $array, $path ) {
    $current = $array;
    foreach( explode( '.', $path ) as $segment ) {
        if( false === array_key_exists( $segment, $current ) ) {
            return false;
        }
        $current = $current[$segment];
    }
    return $current;
}

$path = 'level1.level2.level3';

// will be converted to get the value 'my data' from the array below
$data['level1']['level2']['level3'] = 'my data';

var_dump( retrieve( $data, $path ) );
Sign up to request clarification or add additional context in comments.

4 Comments

You can use isset($current[$segment]) rather than array_key_exists(). It will be a bit faster.
@ScottSaunders You could, but that won't work if the value is "null". That's why I opted for array_key_exists instead.
@Scott will I ever notice this "a bit"?
@ScottSaunders No worries, I take it no other way. It's just that it's 1) different, because null values are "not set" and 2) indeed, it's premature. But thanks for the heads-up, anyway :)
2

It is a tricky one this, here is the most efficient way I can think of:

function get_value_from_array ($array, $path, $pathSep = '.') {
  foreach (explode($pathSep, $path) as $pathPart) { 
    if (isset($array[$pathPart])) {
      $array = $array[$pathPart];
    } else { 
      return FALSE;
    }
  }
  return $array;
}

Returns the value, or FALSE on failure.

4 Comments

The solution suggested by this answer and the one by Berry are similar to what I have implemented, and I am trying to optimize it because if the value being serched for is really deep in the structure (and the array structure could potentially be huge), it means there will be a lot of array copy cycles which will be costly
@Haddad Probably not costly enough for you to worry about it. Unless you are doing this literally hundreds of thousands of times, it shouldn't make enough of a difference to be noticable.
@Haddad Then why, if I might ask, are you doing the foo.bar.path thingy? Why not just $array['foo']['bar']['path']? Do you really need to use the . as a separator?
@Berry I am using that separator based path to give a "namespaced" path to these values, which are serverd as a webservice, so the path is going to be received as an HTTP parameter.
0

Try

$index = "data";
echo $$index['level1']['level2']['level3'];

instead, because $index should be only variable name

5 Comments

Ehm, What's the reason for downvote? Is anyone in rage? Care to explain so I can improve my answer?
This isn't going to help him, as he doesn't have the breakdown of level1/level2/level3. If he did, then there would be no need to use $$index notation
@AleksG: the only thing he need to do is to change 'level1' ... with variables, which wouldn't work with variable name
not really, he has a variable containing level1.level2.level3 - which he can convert to a string containing data['level1']['level2']['level3']
The reason why I want to use variable variable is because the depth of the array is variable, i.e. level1.level2.level3 can also be level1.level2.level3.level4 ....
-1

Something like this:

eval('$data[\''.implode("']['",explode('.',$path))."'] = 'my data';");

...but don't ever, ever tell anyone I told you to do this.

Comments

-1

You can use eval function like so:

$data['level1']['level2']['level3'] = 'my data';
eval("\$index = \$data['level1']['level2']['level3'];");
echo $index;

Comments

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.