【问题标题】:Create parent child admin menu tree using database in laravel在 laravel 中使用数据库创建父子管理菜单树
【发布时间】:2019-05-06 17:51:26
【问题描述】:

我正在开发一个内容管理系统,但在 CMS 中遇到了菜单的父子关系问题。

基本上我有一个可以创建菜单和子菜单的系统。这是数据库中的数组的样子。

 array:6 [
       0 => array:4 [
        "id" => 4
        "name" => "Contacts"
        "order" => 0
        "parent_menu_id" => null
      ]
      1 => array:4 [
        "id" => 1
        "name" => "Leads"
        "order" => 1
        "parent_menu_id" => null
      ]
      2 => array:4 [
        "id" => 2
        "name" => "List Leads"
        "slug" => "list-leads"
        "order" => 1
        "parent_menu_id" => 1
      ]
      3 => array:4 [
        "id" => 5
        "name" => "Edit Leads"
        "slug" => "edit-leads"
        "order" => 1
        "parent_menu_id" => 1
      ]
      4 => array:4 [
        "id" => 3
        "name" => "Create New"
        "slug" => "new"
        "order" => 2
        "parent_menu_id" => 2
      ]
      5 => array:4 [
        "id" => 14
        "name" => "Tasks"
        "slug" => "tasks"
        "order" => 3
        "parent_menu_id" => null
      ]
    ]

我正在使用菜单表中的父 ID 插入菜单和子菜单。如上所述,我正在从 db 中获取菜单。那么,如何以树状结构的层次形式生成/呈现菜单?

我需要遍历一个可以有任意数量导航的数组,并智能地将其排序到它的父子关系中。我能够做到,但只有一层深。它需要管理具有无限层数的子与子等,并将其输出到 HTML 下拉菜单和下拉项嵌套列表。

我正在创建一个函数,它只显示父母和它的孩子,但不显示任何孩子的孩子。我该如何解决?

    public static function render_module_menu() {
          $menus = MenusModel::leftJoin('modules', 'menus.module_id', '=', 'modules.id')->where('modules.enable', 1)->select('menus.*')->orderBy('order')->get()->toArray();

          foreach ($menus as $menu) {
            $childMenus = MenusModel::where('parent_menu_id', $menu['id'])->orderBy('order')->get()->toArray();

            if ($childMenus) {
              echo '<li class="nav-item dropdown">
                      <a class="nav-link dropdown-toggle" href="#" id="pagesDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        <i class="'.$menu['icon'].'"></i>
                        <span>'.$menu['name'].'</span>
                      </a>
                      <div class="dropdown-menu" aria-labelledby="pagesDropdown">';
              foreach ($childMenus as $child) {
                 echo '<a class="dropdown-item" href="'.url($menu['slug'].'/'.$child['slug']).'">
                          <i class="'.$child['icon'].'" style="margin-right: 10px;"></i>
                       '.$child['name'].'</a>';

              }
              echo '</div>
                    </li>';
            } else {
                echo '<li class="nav-item">
                        <a class="nav-link" href="'.url($menu['slug']).'">
                          <i class="'.$menu['icon'].'"></i>
                          <span>'.$menu['name'].'</span></a>
                      </li>';
            }

          }
        }

【问题讨论】:

    标签: php laravel menu


    【解决方案1】:

    第一个功能:

    public static function GenerateMenuArray($arr, $parent = 0)
    {
    $pages = Array();
    foreach($arr as $page)
    {
    if($page['parent_menu_id'] == $parent)
    {
    $page['sub'] = isset($page['sub']) ? $page['sub'] : self::GenerateMenuArray($arr, $page['id']);
    $pages[] = $page;
    }
    }
    return $pages;
    }
    

    第二个功能:

    // loop the multidimensional array recursively to generate the HTML
    public static function GenerateMenuHTML($nav, $level=0)
    {
    $menus = MenusModel::leftJoin('modules', 'menus.module_id', '=', 'modules.id')->select('menus.*')->where('modules.enable', 1)->where('parent_menu_id', null)->orderBy('order')->get()->toArray();
    
    $html = '';
    foreach($nav as $page)
    {
    // dd($page);
    if (empty($page['sub'])) {
    if ($page['parent_menu_id'] == null) {
    $html .= '<li class="nav-item">
    <a class="nav-link" href="'.url($page['slug']).'">
    <i class="'.$page['icon'].'"></i>
    <span>'.$page['name'].'</span></a>
    </li>';
    } else {
    foreach ($menus as $parent) {
    $parent_slug = $parent['slug'];
    if($parent['id'] == $page['parent_menu_id'] AND $page['external'] == 0) {
    $html .= '<a class="dropdown-item" href="'.url($parent_slug.'/'.$page['slug']).'">
    <i class="'.$page['icon'].'" style="margin-right: 10px;"></i>
    '.$page['name'].'</a>';
    }
    }
    
    if ($page['external'] == 1) {
    $html .= '<a class="dropdown-item" href="'.url($page['slug']).'">
    <i class="'.$page['icon'].'" style="margin-right: 10px;"></i>
    '.$page['name'].'</a>';
    }
    
    }
    
    } else {
    if ($level > 0) {
    $html .= '</div></li>';
    }
    $html .= '<li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" id="pagesDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    <i class="'.$page['icon'].'"></i>
    <span>'.$page['name'].'</span></a>
    <div class="dropdown-menu" aria-labelledby="pagesDropdown">';
    
    
    $level = ++$level;
    $html .= self::GenerateMenuHTML($page['sub'], $level);
    $level = --$level;
    
    if ($level > 0) {
    $html .= '</div></li>';
    }
    }
    }
    return $html;
    }
    
    // loop the multidimensional array recursively to generate the HTML
    public static function GenerateNavHTML($nav)
    {
    $html = '';
    foreach($nav as $page)
    {
    $html .= '<ul><li>';
    $html .= '<a href="' . $page['slug'] . '">' . $page['name'] . '</a>';
    $html .= self::GenerateNavHTML($page['sub']);
    $html .= '</li></ul>';
    }
    return $html;
    }
    

    请试试这个。

    【讨论】:

    • 感谢您的努力。 :-)
    【解决方案2】:

    您只是在循环浏览您的菜单及其直接子项。
    这里最好的解决方案是创建一个打印子项的函数,然后在其内部调用该函数,这样只要当前菜单项有子项,它就会一直被调用。

    function printChildren($children){
        foreach($children as $child){
            //(add code to print menu item)
            $moreChildren = //(add code to find children of this menu item)
            printChildren($moreChildren);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-02-06
      • 2018-09-30
      • 2012-03-11
      • 1970-01-01
      • 2020-01-28
      • 2017-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多