2

I have then next 2 tables

/* systems */
id    sys_name
 1    Debtors
 2    Creditors
 3    Cashbook

/* menus */
id    system_id    parent_id   menu_desc
1         1            0       Maintenance
2         1            1       Maintain Debtors
3         1            2       Debtor Addresses
4         1            1       Maintain Clerks
5         3            0       Bank Reconciliation

I have 2 Eloquent models

/* System */
public function menus(){ 
   return this->hasMany(Menu::class,'system_id','id')->where('menus.parent_id','=',0);
}
public function submenus(){ 
   return this->hasMany(Menu::class,'system_id','id')->where('menus.parent_id','=','menus.id');
}

/* Menu */
public function system(){
   return $this->belongsTo(System::class,'system_id','id');
}
public function parent(){
   return $this->hasOne(Menu::class,'id','parent_id');
}
public function children(){ 
   return $this->hasMany(Menu::class,'parent_id','id');
}

I want to achieve the following in blade.php:

@foreach($systems as $system)
   ....... 
   @foreach($menus as $menu)
      .......
      @foreach($submenus as $submenu)
          ........
       @endforeach
    @endforeach
 @endforeach

with the following output: (I am using bootstrap for indentation)

Debtors
   Maintenance
      Maintain Debtors
         Debtor Addresses
      Maintain Clerks
Creditors
Cashbook
   Bank Reconciliation

MenuController

$systems = System::with('menus','submenus')->get();

but it doesn't work. There are no submenu records. I think the problem is 'menus.id' in function submenus() but dont know how to solve it.

Please help as I have battled more than 3 days to build a menu treeview.

Thanking you in advance

2 Answers 2

2

The easiest way to do what you want is to use a nested relation.

Instead of trying to build a ->submenus() relation, instead just use the already-existing ->children() relation on your Menu class:

Route::get('systems', function() {
    $systems = System::with('menus.children')->get();
    return view('systems')->with('systems', $systems);
});

Then your systems.blade.php template can just be something like

<pre>
Systems
@foreach($systems as $system)
    {{$system->sys_name}} Menus
    @foreach($system->menus as $menu)
        {{$menu->menu_desc}} Submenus
        @foreach($menu->children as $submenu)
            {{$submenu->menu_desc}}
        @endforeach
    @endforeach
@endforeach
</pre>

As an additional advantage to that method, you can get all menus with subsubsubmenus with System::with('menus.children.children.children')->get(), and so on.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you Joshua @irfani. Is there any way to found out how deep the levels are that I have to cater for in the blade.php with @foreach?
You'll probably want to use a partial which recursively @includes itself (see here for an example).
0

You need to put the submenus() function on the menu model file, since your tree structure is system menu submenu

or you can just change the with syntax to

$systems = System::with('menus','menus.children')->get();

and change the submenu foreach with $menu.children

@foreach($menu->children as $submenu)

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.