Search code examples
phparraysrecursionsmarty

How to loop over a multidimensional objectArray with Smarty?


In Smarty, how can I iterate over the sub value in my second foreach?

[test] => stdClass Object
        (
            [parent] => Test
            [sub] => Array
                (
                    [0] => Array
                        (
                            [key1] => Value 1
                            [key2] => Value 2
                        )

                )

        )
        
 {foreach from=$menuList item=menu}
    <li><a href="#">{$menu->name}</a>
        <ul class="dropdown-menu">
          {foreach from=$menu->sub key=k item=v}
                <li class="dropdown-submenu" name=>{$v}</li>
          {/foreach}
        </ul>
    {/foreach}
 </li>

How to print second foreach key and value?

It print array string only


Solution

  • First of all your "array" is in fact object. You need to convert it to array first to use that function. Here is a function that can do this:

    function objectToArray($d) {
        if (is_object($d)) {
            // Gets the properties of the given object
            $d = get_object_vars($d);
        }
        if (is_array($d)) {
            /*
            * Return array converted to object
            * Using __FUNCTION__ (Magic constant)
            * for recursive call
            */
            return array_map(__FUNCTION__, $d);
        }
        else {
            // Return array
            return $d;
        }
    }
    

    Obviously this is php function, put it in php file or in smarty plugin to be able to access it. Then, here is a function that is using the previous function to deal dinamically with objects, or whatever input is.

    function smarty_function_tree($params, &$smarty) {
    if (!isset($params['level'])) {
        $level = 0;
        } else {
        $level = $params['level'];
    }
    return tree($params['data'], $level);
    }
    
    function tree($data, $level) {
    echo '<ul class="level', $level, '">', "\r\n";
    $aData = objectToArray($data);
    foreach ($aData as $key => $entry) {
        if (is_array($entry)) {
            echo '<li>', $key, '</li>', "\r\n";
            tree($entry, $level+1);
        } else {
            echo '<li>', $key, ' = ', $entry, '</li>', "\r\n";
        }
    }
        echo '</ul>', "\r\n";
    }
    

    Create a plugin called accordingly to function name, then you can use it in template like this:

    {tree data=$yourObject}
    

    or

    {tree data=$yourArray}
    

    Edit: you also can use litlebit of css to indent the output of the tree function:

    .level0 {
        text-indent: 20px;
    }
    
    .level1 {
        text-indent: 40px;
    }
    
    .level2 {
        text-indent: 60px;
    }
    
    .level3 {
        text-indent: 80px;
    }
    
    .level4 {
        text-indent: 100px;
    }
    
    .level5 {
        text-indent: 120px;
    }
    
    .level6 {
        text-indent: 140px;
    }
    
    .level7 {
        text-indent: 160px;
    }
    
    .level8 {
        text-indent: 180px;
    }
    
    .level9 {
        text-indent: 200px;
    }
    

    Hope it helps!