phparraysrecursiontraversal

Replace verbose nested data traversal with recursive code


I wrote my own function to display array structure in a comfortable way.
It shows array like that:

$data:
$data[id] = 3

$config:
$config[last_offer_day] = 01.07.2023
and etc.

I think my code is too cumbersome.

function darr ($var, $name = '')
{
    if($name) $out = '<b>'.$name.':</b><br>';
    $len = 250;

    foreach($var as $key1=>$val1)
    {
        $key1 = $name ? '['.$key1.']' : '$'.$key1;

        if(is_array($val1) || is_object($val1))
        {
            if(count($val1) > 1) $out .= '<br>'.$key1.':<br>';

            foreach($val1 as $key2=>$val2)
            {
                if(is_array($val2) || is_object($val2))
                {
                    foreach($val2 as $key3=>$val3)
                    {
                        if(is_array($val3) || is_object($val3))
                        {
                            foreach($val3 as $key4=>$val4)
                            {
                                if(is_array($val4) || is_object($val4))
                                {
                                    foreach($val4 as $key5=>$val5)
                                    {
                                        if(is_array($val5) || is_object($val5))
                                        {
                                            foreach($val5 as $key6=>$val6)
                                            {
                                                if(is_array($val6) || is_object($val6))
                                                {
                                                    foreach($val6 as $key7=>$val7)
                                                    {
                                                        $out .= $name.$key1.'['.$key2.']['.$key3.']['.$key4.']['.$key5.']['.$key6.']['.$key7.'] = '.trim((mb_strlen($val7) > $len ? mb_substr($val7, 0, $len).'...' : $val7),' \n').'<br>';
                                                    }
                                                } else $out .= $name.$key1.'['.$key2.']['.$key3.']['.$key4.']['.$key5.']['.$key6.'] = '.trim((mb_strlen($val6) > $len ? mb_substr($val6, 0, $len).'...' : $val6),' \n').'<br>';
                                            }
                                        } else $out .= $name.$key1.'['.$key2.']['.$key3.']['.$key4.']['.$key5.'] = '.trim((mb_strlen($val5) > $len ? mb_substr($val5, 0, $len).'...' : $val5),' \n').'<br>';
                                    }
                                } else $out .= $name.$key1.'['.$key2.']['.$key3.']['.$key4.'] = '.trim((mb_strlen($val4) > $len ? mb_substr($val4, 0, $len).'...' : $val4),' \n').'<br>';
                            }
                        } else $out .= $name.$key1.'['.$key2.']['.$key3.'] = '.trim((mb_strlen($val3) > $len ? mb_substr($val3, 0, $len).'...' : $val3),' \n').'<br>';
                    }
                } else $out .= $name.$key1.'['.$key2.'] = '.trim((mb_strlen($val2) > $len ? mb_substr($val2, 0, $len).'...' : $val2),' \n').'<br>';
            }
        } else $out .= $name.$key1.' = '.trim((mb_strlen($val1) > $len ? mb_substr($val1, 0, $len).'...' : $val1),' \n').'<br>';
    }

    return $out;
}

Is there a way to make my code smaller and simpler?


Solution

  • This uses recursive calls to handle nested arrays or objects. You don't need multiple nested loops, and it also properly handles the display of numeric keys in square brackets.

    function darr($var, $name = '')
    {
        $out = '';
        $len = 250;
    
        if ($name) {
            $out .= '<b>' . $name . ':</b><br>';
        }
    
        if (is_array($var) || is_object($var)) {
            foreach ($var as $key => $val) {
                $keyString = is_numeric($key) ? '[' . $key . ']' : "['" . $key . "']";
                $displayName = $name . $keyString;
    
                if (is_array($val) || is_object($val)) {
                    if (count($val) > 1) {
                        $out .= '<br>' . darr($val, $displayName);
                    } else {
                        $out .= darr($val, $displayName);
                    }
                } else {
                    $out .= $displayName . ' = ' . trim((mb_strlen($val) > $len ? mb_substr($val, 0, $len) . '...' : $val), " \n") . '<br>';
                }
            }
        }
    
        return $out;
    }