Submenus in php and mysql directory style database -


i've been trying make menu submenus on each main item , sub_sub_menus on each sub menu through php , mysql. feel i'm there i'm new php , mysql i've come here help. have been searching hours answer, i've found examples of dropdown menus none this.

not sure how add sql database here try add if requested.

my php code below far.

$result = mysqli_query($link, 'select * library parent_id =' . $parent_id = 0);  $subresult = mysqli_query($link, 'select * library parent_id >'. $parent_id);     if(mysqli_num_rows($result) > 0) {                 echo '<ul class="nav list">';                          while($row = mysqli_fetch_array($result))                         {                             echo '<li class="nav-item">'. '<a href="#">'.$row['mainfolder'] .'</a>'.                               '<ul class="dropdown-content nav">';                             while($sub = mysqli_fetch_array($subresult))                             {                                 if($row['id']===$sub['parent_id'])                                 {                                          echo $sub['parent_id'];                                      $submenuitems = mysqli_query($link, 'select mainfolder library parent_id ='. $sub['parent_id']);                                     $items = mysqli_fetch_array($submenuitems);                                     foreach ($items $eachitem){                                        echo' <li class="submenu">'.'<a class="sub" href="#">'.htmlspecialchars($eachitem, ent_quotes, 'utf-8').'</li>'.'</a>'.'</ul>';                                     }                                 }                             }                          }                             echo '</ul>'.'</li>';                    echo '</ul>';             } 

because asked nicely, , because challenge of recursive functions decided go ahead , out.

my original answer getting bit out of hand, cleaned up. did ton of debugging, , fixed few "bugs" found in original post.

echo "<pre>"; //preserve whitespace  //i mocked arrays ('canned data') make things easier show , test //order of parents matter ( should in order left right of menu ) $parents = [    ['id' => 1, 'title' => 'item1', 'link' => 'http://www.example.com/item1', 'parent_id' => 0],     ['id' => 8, 'title' => 'item8', 'link' => 'http://www.example.com/item8', 'parent_id' => 0], ];  var_export( $parents ); echo "\n\n";  //you can order children way want, still grouped under right parent $children = [     ['id' => 2, 'title' => 'item2', 'link' => 'http://www.example.com/item2', 'parent_id' => 1],             ['id' => 3, 'title' => 'item3', 'link' => 'http://www.example.com/item3', 'parent_id' => 2],     ['id' => 4, 'title' => 'item4', 'link' => 'http://www.example.com/item4', 'parent_id' => 1], //not ordered     ['id' => 5, 'title' => 'item5', 'link' => 'http://www.example.com/item5', 'parent_id' => 2, "target" => null, "css_class" => null],     ['id' => 6, 'title' => 'item6', 'link' => 'http://www.example.com/item6', 'parent_id' => 1, "target" => "_blank"],      ['id' => 7, 'title' => 'item7', 'link' => 'http://www.example.com/item7', 'parent_id' => 8, "css_class"=>"test"],   ];  var_export($children); echo "\n\n";  $lv = 1;  $html = "<ul class=\"menu menu_lv0\" >\n";  foreach( $parents &$parent ){     $html = buildmenutree( $parent, $children, $html, $lv, $lv );   //pass refrence no return needed }  $html .= "</ul>\n";  var_export( $parents ); echo "\n\n";  echo htmlspecialchars( $html )."\n\n"; //htmlspecialchars display reasons   //========================================= //            define function //=========================================  //$parent passed refrence function buildmenutree( &$parent, $children, $html='', $lv=0, $indent=0 ){      if( $lv == 1 || $lv == 2) $mode = true;      if( !$children ) return;     reset( $children ); //reset array      $t0 = getindent( $indent );     $t1 = getindent( ($indent+1) );      //css class menu item     $css_class = (isset($parent['css_class']) && $parent['css_class']) ? " {$parent['css_class']}" : "";     //link target     $target = (isset($parent['target']) &&  $parent['target']) ? "target=\"{$parent['target']}\" " : "";      $id = $parent['id'];      $html .= "{$t0}<li id=\"menu_item_{$id}\" class=\"menu_item item_lv{$lv}{$css_class}\">\n";     $html .= "{$t1}<a class=\"menu_link\" href=\"{$parent['link']}\" {$target}>{$parent['title']}</a>";      while( false !== ( $child = current( $children ) ) ){                    //if parents id, matches childs parent id, add current child         //as child of parent , check ( current child ) children may have         // add  if( ... && $limit == $lv) , pass in $limit param function limit depth         if( $parent['id'] == $child['parent_id'] ){             $key = key( $children );             //remove - reduce array , our processing time, can remove current item             //also current item parent in recusive function , therefore             //know cannot child of , wont need in branch             unset( $children[$key] );               //make recursive call ( call method again             //&$parent, $children, $html='', $lv=1, $indent=1             $r_html = buildmenutree($child, $children, "", ($lv + 1), ($indent+2));              //creante children array if not exists             if( !isset( $parent['children'] ) ){                 $parent['children'] = [];                   $html .= "\n{$t1}<ul class=\"sub_menu menu_lv{$lv} parent_{$parent['id']}\" >\n";                 $html .= $r_html;             }else{                 $html .= $r_html;             }              ///store child             $parent['children'][] = $child;          }else{             $next = next( $children );          };     }      if( !isset( $parent['children'] ) )        $html .= "\n";     else         $html .= "{$t1}</ul>\n";      $html .= "{$t0}</li>\n";      return $html; }  function getindent( $indent, $pad = " " ){     return str_pad("", ( $indent * 4 ), $pad); }  echo "</pre>"; 

i tested on apache/2.4.18 (win32) php/7.0.4) , 100% works.

output

array tree structure parent passed reference, it's modified not returned, need return html

$parent = array (   0 =>    array (     'id' => 1,     'title' => 'item1',     'link' => 'http://www.example.com/item1',     'parent_id' => 0,     'children' =>      array (       0 =>        array (         'id' => 2,         'title' => 'item2',         'link' => 'http://www.example.com/item2',         'parent_id' => 1,         'children' =>          array (           0 =>            array (             'id' => 3,             'title' => 'item3',             'link' => 'http://www.example.com/item3',             'parent_id' => 2,           ),           1 =>            array (             'id' => 5,             'title' => 'item5',             'link' => 'http://www.example.com/item5',             'parent_id' => 2,             'target' => null,             'css_class' => null,           ),         ),       ),       1 =>        array (         'id' => 4,         'title' => 'item4',         'link' => 'http://www.example.com/item4',         'parent_id' => 1,       ),       2 =>        array (         'id' => 6,         'title' => 'item6',         'link' => 'http://www.example.com/item6',         'parent_id' => 1,         'target' => '_blank',       ),     ),   ),   1 =>    array (     'id' => 8,     'title' => 'item8',     'link' => 'http://www.example.com/item8',     'parent_id' => 0,     'children' =>      array (       0 =>        array (         'id' => 7,         'title' => 'item7',         'link' => 'http://www.example.com/item7',         'parent_id' => 8,         'css_class' => 'test',       ),     ),   ), ) 

html

<ul class="menu menu_lv0" >     <li id="menu_item_1" class="menu_item item_lv1">         <a class="menu_link" href="http://www.example.com/item1" >item1</a>         <ul class="sub_menu menu_lv1 parent_1" >             <li id="menu_item_2" class="menu_item item_lv2">                 <a class="menu_link" href="http://www.example.com/item2" >item2</a>                 <ul class="sub_menu menu_lv2 parent_2" >                     <li id="menu_item_3" class="menu_item item_lv3">                         <a class="menu_link" href="http://www.example.com/item3" >item3</a>                     </li>                     <li id="menu_item_5" class="menu_item item_lv3">                         <a class="menu_link" href="http://www.example.com/item5" >item5</a>                     </li>                 </ul>             </li>             <li id="menu_item_4" class="menu_item item_lv2">                 <a class="menu_link" href="http://www.example.com/item4" >item4</a>             </li>             <li id="menu_item_6" class="menu_item item_lv2">                 <a class="menu_link" href="http://www.example.com/item6" target="_blank" >item6</a>             </li>         </ul>     </li>     <li id="menu_item_8" class="menu_item item_lv1">         <a class="menu_link" href="http://www.example.com/item8" >item8</a>         <ul class="sub_menu menu_lv1 parent_8" >             <li id="menu_item_7" class="menu_item item_lv2 test">                 <a class="menu_link" href="http://www.example.com/item7" >item7</a>             </li>         </ul>     </li> </ul> 

i took liberty add few things consider commonly implemented features of navigation menu.

  • css class, if row contains $row ['css_class'] <li> add it's value it's classes, can set false|null or not have it.
  • target, if item contains $row ['target'] <a> tag have target attribute it's value, can set false|null or not have it.

you can see these test cases:

  • most items omit target , css_class don't use word class, because reserved word
  • item5 has both target , css_class set null false value omit these tags.
  • item6 has target value of _blank , link <a target="_blank" .. in output
  • item7 has css_class of test , has these classes menu_item item_lv2 test

here list of classes added html

ul classes:

  • top level <ul> have class of menu
  • sub level <ul> have class of sub_menu
  • sub level <ul> have class of parent_{id} {id} id of parent
  • every <ul> have class of menu_lv{lv} {lv} nesting level

ul classes & id:

  • every <li> have id of menu_item_{id} {id} record id
  • every <li> have class of menu_item
  • every <li> have class of item_lv{lv}where {lv} nesting level

a classes:

  • every <a> tag have class of menu_link

the catch, not set children key in record manually, $parent['children'] or $child['children']. had use way detect if children had been added yet. ( although work refined, didn't seem important )

this took quite bit of work , time, on own css. but, have built many, many menus , html should close need (although, admit, has been few years sense made nav menu).

lastly can test online in phpsanbox link

good luck, , enjoy!


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -