0

Alright I'm working with a large multidimensional array which has more information in it than I need and I want to loop through it to filter the data which I'm interested in. Sadly this multidimensional array is produced dynamically and doesn't always contain the data I want, so I have to use logic like:

if(isset($ar['b']['ba']['baa'])){
echo '<h3>'.$ar['b']['ba']['baa'].'</h3>';
}
if(isset($ar['b']['ba']['baba'])){
echo '<h3>'.$ar['b']['ba']['baba'].'</h3>';
}
if(isset($ar['b']['ba']['babb'])){
echo '<h3>'.$ar['b']['ba']['babb'].'</h3>';
}

The above works great but its a bit messy-looking so I converted the above to:

$refAr=array();
$refAr[]='b->ba->baa';//3
$refAr[]='b->ba->bab->baba';//4
$refAr[]='b->ba->bab->babb';//5

The above looks a lot more nice and neat and is how I want to control the script in case I need to reference different keys in the future. The problem I am having is trying to use the above format to actually reference the array. I thought variable variables would work but apparently it fails. My second attempt using eval worked but I'm not very happy with my solution. This is where I need you guys to come in, is there a better way to do this? Here's my attempt below:

<?php

$ar=array(
    'a'=>array('aa'=>1,'ab'=>2),
    'b'=>array(
        'ba'=>array('baa'=>3,'bab'=>array('baba'=>4,'babb'=>5),'bac'=>array('baca'=>6,'bacb'=>7)),
    )
);


$refAr=array();
$refAr[]='b->ba->baa';//3
$refAr[]='b->ba->bab->baba';//4
$refAr[]='b->ba->bab->babb';//5
foreach($refAr as $ref)
{
    $r=explode('->',$ref);
    $r="\$ar['".implode("']['",$r)."']";
    echo '<h1>'.$r.'</h1>';
    echo '<h3>'.$$r.'</h3>';//undefined
    eval('$t='.$r.';');
    echo "<h3>$t</h3>";//works but uses eval, is there a better way?

}

2 Answers 2

1

You can try

$ar = array();
$ar['b']['ba']['baa'] = 3;
$ar['b']['ba']['bab']['baba'] = 4;
$ar['b']['ba']['bab']['babb'] = 5;

$refAr = array();
$refAr[] = 'b->ba->baa'; // 3
$refAr[] = 'b->ba->bab->baba'; // 4
$refAr[] = 'b->ba->bab->babb'; // 5

foreach ( $refAr as $ref ) {
    $t = $ar;
    foreach ( explode("->", $ref) as $v ) {
        if (!isset($t[$v]))
            break;
        $t = $t[$v];
    }
    is_array($t) and $t = null;
    echo "<h3>$t</h3>";
}

Output

3

4

5

Sign up to request clarification or add additional context in comments.

9 Comments

Not bad, except the explode("->", $ref) inside the foreach - i'm not 100% if it's the same in foreach as it is in for loops (but i would imagine it is), but shouldn't the explode be outside the foreach to prevent the explode() function getting called on every iteration... ><
This works but it doesn't check if the variable exists first, so if the reference is invalid, then it generates a warning when the echo should be skipped if it doesn't exist. Try adding: $refAr[]='b->doesnt->exist';
Just add a condition that checks if array_key_exists($v,$t) and break the loop, not output if true.
@VBAssassin it create a copy of the array as soon as you call foreach it does not matter if its inside or in a variable it would still create a copy .. and that is the only copy
Seems to be working, the is_array($t) part is what I was struggling with. Could you get this thing to work with array references too for references to arrays such as b->ba rather than just strings and numbers?
|
0

I decided to answer my own question. This is what I wound up using:

<?php

//Sample PHP representation of dynamically-pulled JSON data from an untrusted source
$ar=array(
    'a'=>array('aa'=>1,'ab'=>2),
    'b'=>array(
        'ba'=>array('baa'=>3,'bab'=>array('baba'=>4,'babb'=>5),'bac'=>array('baca'=>6,'bacb'=>7)),
    )
);

//Reusable function
function resolveReference($ar,&$ref)
{
    $t = $ar;
    foreach ( explode('->',$ref) as $v )
    {
        if (!array_key_exists($v,$t)){$ref=null;return false;}
        $t = $t[$v];
    }
    $ref=$t;
    return true;
}

//The references I'm interested in but don't know if my dynamic data will contain these keys every time
$refAr=array();
$refAr[]='b->ba->baa';
$refAr[]='b->ba->bab->baba';
$refAr[]='b->ba->bab->babb';
$refAr[]='b->doesnt->exist';


foreach($refAr as $ref)
{
    echo '<h1>'.$ref.'</h1>';
    if(resolveReference($ar,$ref))
    {
        echo '<h3><span style="color:blue;">'.$ref.'</span></h3>';
    }else{
        echo '<h3><span style="color:red;">Alternative text for non-existent expected reference</span></h3>';
    }
}

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.