1

I am doing the function of creating dynamic menu in laravel and I have the tbl_menu table as below:

menu_id   parent_id  menu_name      link       order   
  1           0       Level_1       url_1        1  
  2           0       Level_1       url_2        1
  3           2       Level_2       url_3        2
  4           2       Level_2       url_4        3 
  5           4       Level_3       url_5        3 

I want the result to be an array that looks like this:

-Level_1
        -Level_2
        -Level_2
-Level_1
       _Level_2
       _Level_2
               _Level_3

My code is as follows:

public function SelectAllChildeLv1ByParentId($id){
    $result = DB::table('tbl_menu')->where('parent_id', $id)
            ->orderBy('order', 'asc')->get();
    return $result;
}

public function SelectAllMenuParent(){
        $result = DB::table('tbl_menu')->where('parent_id', 0)
            ->orderBy('order', 'asc')->get();
        return $result;
    }
public function getMenuChildren($listParent, $step = 3)
    {
        $results = [];

        if ($step > 0) {
            $step--;
            if($listParent) {
                foreach($listParent as $index => $parent) {
                    $listChild = $this->SelectAllChildeLv1ByParentId($parent->menu_id);
                    $listChild1 = $this->getMenuChildren($listChild, $step);
                    $results[$index] = $parent;
                    $results[$index]->menu_child = $listChild1;
                }
            }
        }

        return $results;
    }

public function getAllMenus() {
        $allMenuParent = $this->SelectAllMenuParent();
        $results = $this->getMenuChildren($allMenuParent);
        return $results;
    }

The results are correct but are running too many queries. I want to optimize it but haven't figured it out yet. Thanks for any help.

2 Answers 2

3

try :

public function get()
{
  $menu = DB::table('tbl_menu')
  ->orderBy('order', 'asc')->get();
  $parents = $menu->where('parent', 0);
  $items = self::tree($parents, $menu);
  return $items;
}

public function tree($items, $all_items)
{
  $data_arr = array();
  foreach ($items as $i => $item) {
    $data_arr[$i] = $item->toArray(); //all column attributes
    $find = $all_items->where('parent', $item->id);
    //$data_arr[$i]['tree'] = array(); empty array or remove if you dont need it
    if ($find->count()) {
      $data_arr[$i]['tree'] = self::tree($find, $all_items);
    }
  }

  return $data_arr;
}
Sign up to request clarification or add additional context in comments.

Comments

2

Use eloquent.

First, add this to the 'tbl_menu' model:

protected $with = ['children'];

public function children()
{
    return $this->hasMany(YOUR_CLASS_NAME::class, 'parent_id', 'id')->orderBy('order');
}

Now if you call the main menu, and all children.

etc: YOUR_CLASS_NAME::where('parent_id', 0)->get().

Then you can use recursion when calling

public $menus = [];
public $level = 0;

public function getMenus($request){
    $menus = YOUR_CLASS_NAME::where('parent_id', 0)
        ->orderBy('order')
        ->get();

    $this->recursiveMenu($menus);

    return $this->menus;
}

public function recursiveMenu($menus, $lvl = 0){
    foreach ($menus as $key => $menu) {
        $this->menus[$menu->id] = str_repeat('—', $lvl).' '.$menu->title;

        if($menu->children){
            $this->level++;
            $this->recursiveMenu($menu->children, $this->level);
        }
        if (!isset($menu[$key+1])) {
            $this->level--;
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.