php - How to use a string as an array index path to retrieve a value?

40

Let say I have an array like:

Array
(
    [0] => Array
        (
            [Data] => Array
                (
                    [id] => 1
                    [title] => Manager
                    [name] => John Smith
                )
         )
    [1] => Array
        (
            [Data] => Array
                 (
                     [id] => 1
                     [title] => Clerk
                     [name] =>
                         (
                             [first] => Jane
                             [last] => Smith
                         )
                 )

        )

)

I want to be able to build a function that I can pass a string to that will act as the array index path and return the appropriate array value without usingeval(). Is that possible?

function($indexPath, $arrayToAccess)
{
    // $indexPath would be something like [0]['Data']['name'] which would return 
    // "Manager" or it could be [1]['Data']['name']['first'] which would return 
    // "Jane" but the amount of array indexes that will be in the index path can 
    // change, so there might be 3 like the first example, or 4 like the second.

    return $arrayToAccess[$indexPath] // <- obviously won't work
}
284

Answer

Solution:

A Bit later, but... hope helps someone:

// $pathStr = "an:string:with:many:keys:as:path";
$paths = explode(":", $pathStr); 
$itens = $myArray;
foreach($paths as $ndx){
    $itens = $itens[$ndx];
}

Now itens is the part of the array you wanted to.

[]'s

Labs

424

Answer

Solution:

you might use an array as path (from left to right), then a recursive function:

$indexes = {0, 'Data', 'name'};

function get_value($indexes, $arrayToAccess)
{
   if(count($indexes) > 1) 
    return get_value(array_slice($indexes, 1), $arrayToAccess[$indexes[0]]);
   else
    return $arrayToAccess[$indexes[0]];
}
932

Answer

Solution:

This is an old question but it has been referenced as this question comes up frequently.

There are recursive functions but I use a reference:

function array_nested_value($array, $path) {
    $temp = &$array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    return $temp;
}

$path  = array(0, 'Data', 'Name');
$value = array_nested_value($array, $path);
558

Answer

Solution:

Try the following where $indexPath is formatted like a file path i.e.

'<array_key1>/<array_key2>/<array_key3>/...'.

function($indexPath, $arrayToAccess)
{
    $explodedPath = explode('/', $indexPath);
    $value =& $arrayToAccess;
    foreach ($explodedPath as $key) {
        $value =& $value[$key];
    }
    return $value;
}

e.g. using the data from the question, $indexPath = '1/Data/name/first' would return $value = Jane.

493

Answer

Solution:

function($indexPath, $arrayToAccess)
{
    eval('$return=$arrayToAccess'.$indexPath.';');
    return $return;
}
750

Answer

Solution:

You have to parse indexPath string. Chose some separator (for example "."), read text until "." that would be the first key, then read rest until next, that would be next key. Do that until no more dots.

You ken store key in array. Do foreach loop on this array to get seeked element.

155

Answer

Solution:

Here is one way to get the job done, if string parsing is the way you want to go.

$data[0]["Data"]["stuff"] = "cake";

$path = "[0][\"Data\"]['stuff']";

function indexPath($path,$array){
    preg_match_all("/\[['\"]*([a-z0-9_-]+)['\"]*\]/i",$path,$matches);

    if(count($matches[1]) > 0) {
        foreach ($matches[1] as $key) {
                if (isset($array[$key])) {
                        $array = $array[$key];
                } else {
                        return false;
                }
        }
    } else {
        return false;
    }

return $array;
}

print_r(indexPath($path,$data));
556

Answer

Solution:

Apreg_match_all, cycling through the matched results would give you CLOSE to the result you wanted. You need to be careful with all of the strategies listed here for lost information. For instance, you have to devise some way to ensure that 55 stays as type int and isn't parsed as type string.

601

Answer

Solution:

In addition to AbraCadaver:

function array_nested_value($array, $path) {

    foreach($path as $key) {

        $array = $array[$key];
    }

    return $array;
}

$path  = array(0, 'Data', 'Name');
$value = array_nested_value($array, $path);

Possible use

function get_array_value($array=array(), $path=array()){

    foreach($path as $key) {

        if(isset($array[$key])){

            $array=$array[$key];
        }
        else{

            $array=NULL;
            break;
        }
    }

    return $array;
}

function custom_isset($array=array(), $path=array()){

    $isset=true;

    if(is_array($array)&&is_null(get_array_value($array, $path))){

        $isset=false;
    }

    return $isset;
}

function is($array=array(), $path=array()){

    $is=false;

    if(is_array($array)){

        $array_value=get_array_value($array, $path);

        if(is_bool($array_value)){

            $is=$array_value;
        }
    }

    return $is;
}

Example

    $status=[];

    $status['updated']=true;

        if(is($status,array('updated'))){

                //do something...

        }

Resources

https://gist.github.com/rafasashi/0d3ebadf08b8c2976a9d

627

Answer

Solution:

If you already know the exact array element that you are pulling out why write a function to do it? What's wrong with just

$array[0]['data']['title']

People are also looking for solutions to the problem: xml - PHP xpath not able to find child node but finds parent

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.