Создайте вложенный список из массива PHP для поля выпадающего списка

Я борюсь с массивом, который я хочу превратить в вложенный <select>

Мне нужно:

<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> 

Я не могу работать с optgroup, потому что все можно выбрать. Насколько я знаю, вы не можете выбирать метки optgroup.

Мой массив выглядит так:

 [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 ) 

Мне кажется, что я пробовал десятки вариантов, но я не могу правильно выбрать форму.

Это была моя последняя попытка:

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

Но таким образом, он упорядочен по идентификатору, а вложенность теряет смысл.

Я постараюсь продолжать, но если кто-то может помочь, я ценю любую помощь!


EDIT: данные PHP


Моя функция, чтобы получить все категории из БД:

 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; } 

Мой view.php, где я выводю все данные:

 $query = $this->datei_model->get_categories('all'); foreach ($query as $row) { $parents[] = $row; } $tree = buildTree($parents); print("<select>\n"); printTree($tree); print("</select>"); 

Попробуй это;

 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>"); 

Вывод;

 <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> 

И в вашем случае;

 <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> 

это просто litle изменение исходного кода, на который ответил 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']); } } } 

Теперь пунктирное название отлично работает. *Извините за мой английский

В коде Кереми просто измените эту строку, и код не даст вам каких-либо инкрементирующих тире

 $t['parent'] == $p 

to ->

 $t['parent'] == 0