Laravel and infinity categories as a tree - php

how to display all categories, with sub, sub, sub (..) category, I have simple table:
and my model:
class Category extends Model
{
public $fillable = [
'parent_id',
'name',
'description'
];
public function parent()
{
return $this->belongsTo(Category::class, 'parent_id', 'id');
}
public function children()
{
return $this->hasMany(Category::class, 'parent_id', 'id');
}
}
I want to get:
<ul>
<li>Category
<ul>
<li>Category 1.1</li>
<li>Category 1.2</li>
</ul>
</li>
(...)
</ul>

This practical approach work for n number of categories with n number of children
First create a partial view category.blade.php file which recursively will call itself to load its children
<li>
#if ($category->children()->count() > 0 )
<ul>
#foreach($category->children as $category)
#include('category', $category) //the magic is in here
#endforeach
</ul>
#endif
</li>
Then in the main view you add this code which loads all children recursively
<ul>
#foreach ($categories as $category)
#if($category->parent_id == 0 )
#include('category', $category)
#endif
#endforeach
</ul>

Related

How to pass parameter to model function from view?

I have tree structure of categories. Now I have to display only that categories which is not applied in a particular business.
Code in Controller
public function edit($id)
{
try
{
$id=Crypt::decrypt($id);
$business=Business::findOrFail($id);
$business_contact_details=BusinessContactDetails::where('business_id',$id)->select('contact_no','id')->get();
$business_working_hours=BusinessWorkingHours::where('business_id',$id)->get();
$business_categories=BusinessCategories::leftJoin('categories','categories.id','=','category_id')->where('business_id',$id)->where('categories.parent_id','0')->select('categories.name as name','approved','category_id','business_categories.id as id')->get();
$categories = Categories::where('parent_id', '=', 0)->get();
return view('admin.businesses.edit',compact('business','business_contact_details','business_working_hours','categories','category_counter','business_categories'));
}
catch(DecryptException $e)
{
return view('errors.404');
}
}
Code in Model
public function subChilds(){
return $this->hasMany('App\Categories','parent_id','id')->whereNotExists(function($query){
$query->from('business_categories')->whereRaw('categories.id=business_categories.category_id')->where('business_id',2);
});
}
Code in edit View
<div class="col-md-6">
<ul id="tree1">
#foreach($categories as $category)
<li>
<input type="checkbox" value="{{$category->id}}" name="categories[]">
{{ $category->name }}
#if(count($category->subChilds($business->id)))
#include('admin.businesses.manageChildSub',['subChilds' => $category->subChilds($business->id)])
#endif
</li>
#endforeach
</ul>
</div>
Code in manageChildSub View
<ul>
#foreach($subChilds as $child)
<li>
<input type="checkbox" value="{{$child->id}}" name="categories[]">
{{ $child->name }}
#if(count($child->childs))
#include('manageChildSub',['subChilds' => $child->subChilds($business->id)])
#endif
</li>
#endforeach
</ul>
Here, You can see that I have passed business_id as 2, but I have to pass it as my current business ID. Basically I need to call the model function with ID.
After changing to this, I am not getting any subcategories.
You can try this:
public function subChilds($business_id){
return $this->hasMany('App\Categories','parent_id','id')
->whereNotExists(function($query) use ($business_id){
$query->from('business_categories')
->whereRaw('categories.id=business_categories.category_id')
->where('business_id', $business_id);
});
}

How to list Category - Subcategory in navigation menu in Laravel

How to list Category - Subcategory in the navigation menu in Laravel?
I have a query like this below.
id Title parent_id
1 cat1 1
2 cat2 1
3 cat3 2
4 cat4 3
add these functions to your model
public function children()
{
return $this->hasMany(Category::class, 'parent_id', 'id');
}
public function parent()
{
return $this->belongsTo(Category::class, 'parent_id', 'id');
}
Then in your view:
#foreach ($categories as $category)
#if($category->parent_id == 0)
#include('categories.view', $category)
#endif
#endforeach
And the is content of categories.view.blade file
<li id="{{$category->id}}" data-jstree='{"icon":"fa {{$category->icon}}"}'>
{{ $category->name }}
#if ($category->children()->count() > 0)
<ul>
#foreach($category->children as $category)
#include('categories.view', $category)
#endforeach
</ul>
#endif
</li>

How to use two foreachs in laravel?

I have a category table, it is organized by 'parent_id' and 'categoryid'. I need to organize it in a list, where I group the parent class with the daughter class.
I created this code.
In the controller I get the value of the categories.
public function index()
{
$cat1 = Category::where('erp_parentid', '=', 0)->get();
foreach($cat1 as $categoria1){
$cat2 = Category::where('erp_parentid', '=', $categoria1->erp_categoryid)->get();
return view('admin.categories')->with('cat1', $cat1)->with('cat2', $cat2);
}
}
$cat2 is the child category, I get its values through the categoryid of the parent category.
But when I pass the values to the view, all parent categories take the same value as the first.
I used that code to display the values in the view:
<div class="container">
<div class="row">
<ul class="list-group">
#foreach($cat1 as $value)
<a data-toggle="collapse" data-target="#catfilha{{$value->erp_categoryid}}"><li class="list-group-item">{{$value->erp_name}}</li></a>
<ul id="catfilha{{$value->erp_categoryid}}" class="collapse">
#foreach($cat2 as $value2)
<li>{{$value2->erp_name}}</li>
#endforeach
</ul>
#endforeach
</ul>
</div>
</div>
I searched for similar cases here on the site, but found no resemblance, any suggestions? Thank you in advance.
You should define the relations in the model and call them in the view. Try something like this:
In Category Model:
public function getParent()
{
return self::where('erp_parentid', '=', $this->erp_categoryid)->get();
}
In Controller:
public function index()
{
$cat1 = Category::where('erp_parentid', '=', 0)->get();
return view('admin.categories')->with('cat1', $cat1);
}
In the View:
<div class="container">
<div class="row">
<ul class="list-group">
#foreach($cat1 as $value)
<a data-toggle="collapse" data-target="#catfilha{{$value->erp_categoryid}}"><li class="list-group-item">{{$value->erp_name}}</li></a>
<ul id="catfilha{{$value->erp_categoryid}}" class="collapse">
#foreach($value->getParent() as $value2)
<li>{{$value2->erp_name}}</li>
#endforeach
</ul>
#endforeach
</ul>
</div>
</div>
In your code, the return statement is inside the loop, so cat2 will be always the categories from the first item of cat1.

dynamic menu in laravel

Im trying to create dynamic menu. Basically,I have two tables :Category and pages.Not sure how should I do this but following is something I have tried
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="{{url('/',null)}}" class="pull-left">Consulate</a>
</div>
<div>
<ul class="nav navbar-nav">
<li class="active">Home</li>
#foreach($categories as $category )
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{$category->title}}<span class="caret"></span></a>
<ul class="dropdown-menu">
#foreach($pages as $page)
<li>{{$page->title}}</li>
#endforeach
</ul>
</li>
#endforeach
With above code, I got the same drop down menus in all the categories.I require dropdown only if the category have pages.
example1
example2
My models looks like following:
Pages model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Pages extends Model
{
protected $fillable=[
'title',
'details',
'image',
'category_id',
];
//A page has a category
public function category()
{
return $this->belongsTo('App\Categories');
}
}
categories model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Categories extends Model
{
protected $fillable=[
'title',
'details',
];
public function pages()
{
return $this->hasMany('App\Pages');
}
}
You could store your categories in a database table called categories (id, name, url). You could then also have another table called pages (id, name, url, category_id).
Create a Category and Page model.
Define a one-to-many relationship (one category-to-many pages).
You could then do:
#foreach( $categories as $category )
<!-- display your category html -->
#foreach( $category->pages as $page )
<!-- display your page html -->
#endforeach
#endforeach
Have a look at one-to-many relaitonships in Laravel: Eloquent: Relationships - one-to-many

How to make menu and submenu dynamic Laravel

I want to make menu and submenu dynamic .I made menu with their link but unable to make submenu,please help me my database structure
table name:menu
id menu_name url timestamps
table:sub_menu
id submenu_name link menu_id timestamps
my query is like this
public function menu()
{
$sql=\DB::table('menu')->rightjoin('sub_menu','menu.id','=','sub_menu.menu_id')
->select('submenu_name','link','url','menu_id','menu_name','menu.id')->get();
return view('products.show.menu',compact('sql'));
}
view
<ul>
#foreach($sql as $key => $nav)
#if($key > 0)
<li>
{{$nav->menu_name}}
#if (count($nav->submenu_name) > 0 )
<ul>
#foreach($nav->submenu_name as $child)
<li>{{$child->submenu_name}}</li>
#endforeach
#endif
</ul>
</li>
#endif
#endforeach
</ul>
Have you set up models for these tables? Your query will return multiple rows for each menu/submenu combination, meaning you can't just iterate over it as you are. There's no need to use the query builder here.
Assuming your models are set up as follows (you will need to check the namespace used in the relationships):
class Menu extends Eloquent
{
protected $table = 'menu';
public function submenu()
{
return $this->hasMany('App\SubMenu');
}
}
class SubMenu extends Eloquent
{
protected $table = 'sub_menu';
public function menu()
{
return $this->belongsTo('App\Menu');
}
}
In your controller, you can do:
public function menu()
{
$menu = Menu::with('submenu')->get();
return view('products.show.menu', compact('menu'));
}
Then in your view:
<ul>
#foreach($menu as $menuItem)
<li>
{{ $menuItem->menu_name }}
#if( ! $menuItem->submenu->isEmpty())
<ul>
#foreach($menuItem->submenu as $subMenuItem)
<li>{{ $subMenuItem->submenu_name }}</li>
#endforeach
</ul>
#endif
</li>
#endforeach
</ul>
You can use it without controller
`#foreach(App\Menu::get() as $menuItem)
#if( ! $menuItem->submenu->isEmpty() )
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
{{ $menuItem->menu_name }}
</a>
#else
<li>
{{ $menuItem->menu_name }}
#endif
#if( ! $menuItem->submenu->isEmpty())
<ul class="dropdown-menu" role="menu">
#foreach($menuItem->submenu as $subMenuItem)
<li>{{ $subMenuItem->submenu_name }}</li>
#endforeach
</ul>
#endif
</li>
#endforeach`

Categories