How to recursively build a <select> with an unknown tree depth

I have a MySQL table with a tree data structure. Fields _id, nameand parentId. When a record does not have a parent, it parentIdis used as 0 by default. This way I can build an array and then print each record recursively.

The built-in array is as follows:

Array
(
    [1] => Array
        (
            [parentId] => 0
            [name] => Countries
            [_id] => 1
            [children] => Array
                (
                    [2] => Array
                        (
                            [parentId] => 1
                            [name] => America
                            [_id] => 2
                            [children] => Array
                                (
                                    [3] => Array
                                        (
                                            [parentId] => 2
                                            [name] => Canada
                                            [_id] => 3
                                            [children] => Array
                                                (
                                                    [4] => Array
                                                        (
                                                            [parentId] => 3
                                                            [name] => Ottawa
                                                            [_id] => 4
                                                        )

                                                )

                                        )

                                )

                        )

                    [5] => Array
                        (
                            [parentId] => 1
                            [name] => Asia
                            [_id] => 5
                        )

                    [6] => Array
                        (
                            [parentId] => 1
                            [name] => Europe
                            [_id] => 6
                            [children] => Array
                                (
                                    [7] => Array
                                        (
                                            [parentId] => 6
                                            [name] => Italy
                                            [_id] => 7
                                        )

                                    [11] => Array
                                        (
                                            [parentId] => 6
                                            [name] => Germany
                                            [_id] => 11
                                        )

                                    [12] => Array
                                        (
                                            [parentId] => 6
                                            [name] => France
                                            [_id] => 12
                                        )

                                )

                        )

                    [8] => Array
                        (
                            [parentId] => 1
                            [name] => Oceania
                            [_id] => 8
                        )

                )

         )

 )

Printing an unordered list is <ul>very easy with recursion. Here is the function I'm using:

function toUL ($arr) {

    $html = '<ul>' . PHP_EOL;

    foreach ( $arr as $v ) {

        $html.= '<li>' . $v['name'] . '</li>' . PHP_EOL;

        if ( array_key_exists('children', $v) ) {
            $html.= toUL($v['children']);
        }

    }

    $html.= '</ul>' . PHP_EOL;

    return $html;
}

But I'm stuck when printing in a <select>tree-like way:

Countries
-- America
---- Canada
------ Ottawa
-- Asia
-- Europe
---- Italy
---- Germany
---- France
-- Oceania

I thought to print --as many times as the depth of an element, but I don’t know how to calculate the depth.

My question is: is it possible to build <select>without knowing depth?

Thanks in advance.

+5
8

, $pass

function toUL ($arr, $pass = 0) {

    $html = '<ul>' . PHP_EOL;

    foreach ( $arr as $v ) {           

        $html.= '<li>';
        $html .= str_repeat("--", $pass); // use the $pass value to create the --
        $html .= $v['name'] . '</li>' . PHP_EOL;

        if ( array_key_exists('children', $v) ) {
            $html.= toUL($v['children'], $pass+1);
        }

    }

    $html.= '</ul>' . PHP_EOL;

    return $html;
}
+6

SPL. RecursiveIteratorIterator Docs :

$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array), SELF_FIRST);
foreach ($it as $key => $element)
{
    if ($key !== 'name') continue;
    $inset = str_repeat('--', $it->getDepth());
    printf('<option>%s %s</option>', $inset, $element);
}
+3
function toSelect($arr, $depth = 0) {

    $html = '';

    foreach ( $arr as $v ) {           

        $html.= '<option>' . str_repeat("--", $depth) . $v['name'] . '</option>' . PHP_EOL;

        if ( array_key_exists('children', $v) ) {
            $html.= toSelect($v['children'], $depth++);
        }

    }


    return $html;
}
+1

( Starx varan):

function toSelect ($arr, $depth=0) {    
    $html = '';
    foreach ( $arr as $v ) {

        $html.= '<option value="' . $v['_id'] . '">';
        $html.= str_repeat('--', $depth);
        $html.= $v['name'] . '</option>' . PHP_EOL;

        if ( array_key_exists('children', $v) ) {
            $html.= toSelect($v['children'], $depth+1);
        }
    }

    return $html;
}

echo '<select>';
echo toSelect($array);
echo '</select>';

RecursiveIteratorIterator ( hakre).

+1

, , - : $tree:

   Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [nombre] => Category 1
            [subcategorias] => Array
                (
                    [0] => stdClass Object
                        (
                            [id] => 4
                            [nombre] => Category 1.1
                        )

                )

        )

    [1] => stdClass Object
        (
            [id] => 2
            [nombre] => Category 2
        )

    [2] => stdClass Object
        (
            [id] => 3
            [nombre] => Category 3
            [subcategorias] => Array
                (
                    [0] => stdClass Object
                        (
                            [id] => 5
                            [nombre] => Category 3.1
                            [subcategorias] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [id] => 6
                                            [nombre] => Category 3.1.1
                                        )

                                )

                        )

                )

        )

)

HTML:

    $tree=array();// PUT HERE YOUR TREE ARRAY
    $arrayiter = new RecursiveArrayIterator($tree);
    $iteriter = new RecursiveIteratorIterator($arrayiter);
    $lista=array();
    $i=0;
    foreach ($iteriter as $key => $value) 
    {
        $id=$iteriter->current();
        $iteriter->next();
        $nivel=$iteriter->getDepth();
        $nombre=str_repeat('-',$nivel-1).$iteriter->current();
        $lista[$id]=$nombre;
    }

- :

    Array
(
    [1] => Category 1
    [4] => --Category 1.1
    [2] => Category 2
    [3] => Category 3
    [5] => --Category 3.1
    [6] => ----Category 3.1.1
)

foreach.

+1
source

You can pass the length of the function and increase it when you call recursively, and then use the variable $lengthto determine the depth

function toUL ($arr, $length = 0) {

    $html = '<ul>' . PHP_EOL;

    foreach ( $arr as $v ) {

        $html.= '<li>' . $v['name'] . '</li>' . PHP_EOL;

        if ( array_key_exists('children', $v) ) {
            $html.= toUL($v['children'], $length++);
        }

    }

    $html.= '</ul>' . PHP_EOL;

    return $html;
}

This is what I usually do to track the depth of the recursion and usually do the work

0
source
function toUL ($arr, $depth = 0) {
//    ...
$html .= toUL($v['children'], $depth+1);
0
source

you can use optgroup as an iterator. For instance:

<select name="list">
  <option value=1>1st option</option>
  <optgroup>
    <option value=10>1st on 1st group</option>
  </optgroup>
</select>

if you want php you can try the following:

<?PHP
function toSELECT($arr,$depth=0)
{
$html="";
if(is_array($arr))
    {
    $html.=($depth==0)?"<select name='html'>\n":"";
    foreach ($arr as $key=>$value)
        {
        if(is_array($arr[$key]))
            {
            $html.=str_repeat("\t",$depth)."<optgroup>\n";
            $html.=str_repeat("\t",$depth).toHTML($arr[$key],$depth+1);
            $html.=str_repeat("\t",$depth)."</optgroup>\n";
            }
        else
            {
            $html.=str_repeat("\t",$depth)."<option value='".$value."'>".$key."</option>\n";
            }
        }
    $html.=($depth==0)?"</select>\n":"";
    }
return $html;
}

?>
0
source

All Articles