Ad

Laravel 5 Eloquent Recursive Programming

- 1 answer

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

Ad

Answer

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.

Ad
source: stackoverflow.com
Ad