Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am struggling with an array I want to turn into a nested < select >

I need:

<select>
<option value="1">Top1</option>
<option value="2">Top2</option>
<option value="9">Top3</option>
<option value="7"> - - Top3.1</option>
<option value="5"> - - Top3.2</option>
<option value="12">- - - - Top3.2.1</option>
<option value="6">Top4</option>
<option value="4">Top5</option>
<option value="8"> - - Top5.1</option>
<option value="3"> - - Top5.2</option>

I can't work with optgroup, because everything is selectable. As far as I know, you can't select optgroup labels.

My array looks like this:

[44] => Array
    (
        [id] => 1
        [name] => Test
        [slug] => test
        [parent] => 0
    )

[45] => Array
    (
        [id] => 2
        [name] => Test-Sub
        [slug] => test-sub
        [parent] => 1
    )

[46] => Array
    (
        [id] => 3
        [name] => Test-Sub-Sub
        [slug] => test-sub-sub
        [parent] => 2
    )

I am feeling like I have tried dozens of variantions, but I can't build my form select right.

That was my last try:

function toDropdown($arr)
    {
        foreach ($arr as $row) {
            $cat[$row['id']] = $row['name'];
            if ($row['parent'] != 0) {
                $cat[$row['id']] = '--' . $row['name'];
            }
        }
        return $cat;
    }

But this way, it is ordered by the ID and the nesting loses its meaning.

I'll try to go on, but if someone can help I appreciate any help!


EDIT: PHP Data


My function to get all categories from the DB:

function get_categories($parent = 'all')
{
    $this->db->select('categories.id, categories.name, categories.slug, categories.parent');
    $this->db->from('categories');

    if ($query = $this->db->get())
    {
        return $query->result_array();
    }

    return FALSE;
}

My view.php, where I output all data:

$query = $this->datei_model->get_categories('all');

foreach ($query as $row)
{
    $parents[] = $row;
}

$tree = buildTree($parents);

print("<select>\n");
printTree($tree);
print("</select>");
share|improve this question

2 Answers 2

up vote 7 down vote accepted

Try this;

function buildTree(Array $data, $parent = 0) {
    $tree = array();
    foreach ($data as $d) {
        if ($d['parent'] == $parent) {
            $children = buildTree($data, $d['id']);
            // set a trivial key
            if (!empty($children)) {
                $d['_children'] = $children;
            }
            $tree[] = $d;
        }
    }
    return $tree;
}


$rows = array(
    array ('id' => 1, 'name' => 'Test 1', 'parent' => 0),
    array ('id' => 2, 'name' => 'Test 1.1', 'parent' => 1),
    array ('id' => 3, 'name' => 'Test 1.2', 'parent' => 1),
    array ('id' => 4, 'name' => 'Test 1.2.1', 'parent' => 3),
    array ('id' => 5, 'name' => 'Test 1.2.2', 'parent' => 3),
    array ('id' => 6, 'name' => 'Test 1.2.2.1', 'parent' => 5),
    array ('id' => 7, 'name' => 'Test 2', 'parent' => 0),
    array ('id' => 8, 'name' => 'Test 2.1', 'parent' => 7),
);

$tree = buildTree($rows);
// print_r($tree);

function printTree($tree, $r = 0, $p = null) {
    foreach ($tree as $i => $t) {
        $dash = ($t['parent'] == 0) ? '' : str_repeat('-', $r) .' ';
        printf("\t<option value='%d'>%s%s</option>\n", $t['id'], $dash, $t['name']);
        if ($t['parent'] == $p) {
            // reset $r
            $r = 0;
        }
        if (isset($t['_children'])) {
            printTree($t['_children'], ++$r, $t['parent']);
        }
    }
}


print("<select>\n");
printTree($tree);
print("</select>");

Output;

<select>
    <option value='1'>Test 1</option>
    <option value='2'>- Test 1.1</option>
    <option value='3'>- Test 1.2</option>
    <option value='4'>-- Test 1.2.1</option>
    <option value='5'>-- Test 1.2.2</option>
    <option value='6'>--- Test 1.2.2.1</option>
    <option value='7'>Test 2</option>
    <option value='8'>- Test 2.1</option>
</select>

And in your case;

<select>
    <option value='1'>Baden-Württemberg</option>
    <option value='2'>- DMP-Verträge</option>
    <option value='50'>- Sprechstundenbedarf</option>
    <option value='52'>- Richtgrößen</option>
    <option value='53'>- Prüfungen</option>
    <option value='54'>- DMP-Verträge</option>
    <option value='55'>- Sonstige Verträge</option>
    <option value='3'>Berlin</option>
    <option value='62'>- DMP-Verträge</option>
    <option value='63'>- Prüfungen</option>
    <option value='64'>- Richtgrößen</option>
    <option value='65'>- Sonstige Verträge</option>
    <option value='66'>- Sprechstundenbedarf</option>
    <option value='4'>Brandenburg</option>
    <option value='67'>- DMP-Verträge</option>
    <option value='68'>- Prüfungen</option>
    <option value='69'>- Richtgrößen</option>
    <option value='70'>- Sonstige Verträge</option>
    <option value='71'>- Sprechstundenbedarf</option>
    <option value='5'>Bremen</option>
    <option value='72'>- DMP-Verträge</option>
    <option value='73'>- Prüfungen</option>
    <option value='74'>- Richtgrößen</option>
    <option value='75'>- Sonstige Verträge</option>
    <option value='76'>- Sprechstundenbedarf</option>
    <option value='7'>Hessen</option>
    <option value='6'>Hamburg</option>
    <option value='8'>Mecklenburg-Vorpommern</option>
    <option value='9'>Niedersachsen</option>
    <option value='10'>Nordrhein</option>
    <option value='11'>Rheinland-Pfalz</option>
    <option value='12'>Saarland</option>
    <option value='13'>Sachsen</option>
    <option value='14'>Sachsen-Anhalt</option>
    <option value='15'>Schleswig-Holstein</option>
    <option value='16'>Thüringen</option>
    <option value='17'>Westfalen-Lippe</option>
    <option value='51'>Richtgrössen</option>
    <option value='56'>Bayern</option>
    <option value='57'>- DMP-Verträge</option>
    <option value='58'>- Prüfungen</option>
    <option value='59'>- Richtgrößen</option>
    <option value='60'>- Sonstige Verträge</option>
    <option value='61'>- Sprechstundenbedarf</option>
</select>
share|improve this answer
    
Wow, thanks!! The code prints my select list quite well. But with every level deeper there is a dash more. <option value='1'> First </option> <option value='2'>- Example </option> <option value='50'>- Example </option> <option value='3'> Example </option> <option value='62'>-- Example </option> <option value='63'>-- Example </option> (…) <option value='56'> Example </option> <option value='60'>----- Example </option> <option value='79'> Example </option> <option value='77'>------ Example </option> <option value='78'>------- Example </option> (Sorry, can't format the code here) –  suntrop Jan 30 '13 at 23:15
    
So, what is problem??? There are also dash more for deeper levels. –  Qeremy Jan 30 '13 at 23:21
    
Yes, your're right. But, for example, the last sub level hast not one dash, but 7 dashes, although it is only on the second level. project-point.de/sub-levels.png –  suntrop Jan 30 '13 at 23:32
    
It's related with your $rows structure, see $rows in answer and check differences, or show your $rows too (but real row data, not print_r'ed). –  Qeremy Jan 30 '13 at 23:37
    
I think both are structured the same way, don't they? Array ( [0] => Array ( [id] => 1 [name] => Baden-Württemberg [slug] => baden-wuerttemberg [parent] => 0 ) [40] => Array ( [id] => 73 [name] => Prüfungen [slug] => pruefungen [parent] => 5 ) ) –  suntrop Jan 30 '13 at 23:41

this just litle change of the original code that answered by Qeremy

function printTree($tree, $r = 0, $p = null) {
    foreach ($tree as $i => $t) {
        $dash = ($t['parent'] == 0) ? '' : str_repeat('-', $r) .' ';
        printf("\t<option value='%d'>%s%s</option>\n", $t['id'], $dash, $t['name']);
        if (isset($t['_children'])) {
            printTree($t['_children'], $r+1, $t['parent']); 
        }
    }
}

Now the dashed name works great. *sorry for my english

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.