Hi there
I have one problem with categories and sub-categories
I have table like:
ID----- Name---- ParentID
1 ------- A ---------
Migration the following Category Table:
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->tinyInteger('parent_id')->default(0);
$table->timestamps();
});
Input Your Category and Sub-Category Like following Table Structure:
+-------------+----------------------+----------+
| id | name |parent_id |
+-------------+----------------------+----------+
| 1 | ELECTRONICS | 0 |
| 2 | TELEVISIONS | 1 |
| 3 | TUBE | 2 |
| 4 | LCD | 2 |
| 5 | PLASMA | 2 |
| 6 | PORTABLE ELECTRONICS | 1 |
| 7 | MP3 PLAYERS | 6 |
| 8 | FLASH | 7 |
| 9 | CD PLAYERS | 6 |
| 10 | 2 WAY RADIOS | 6 |
+-------------+----------------------+----------+
MySQL hierarchical recursive query
$categories = DB::table('categories as c1')
->leftJoin('categories as c2','c2.parent_id','=','c1.id')
->leftJoin('categories as c3','c3.parent_id','=','c2.id')
->leftJoin('categories as c4','c4.parent_id','=','c3.id')
->select('c1.id as c1_id','c1.name as c1_name','c2.id as c2_id','c2.name as c2_name','c3.id as c3_id','c3.name as c3_name','c4.id as c4_id','c4.name as c4_name')
->where('c1.parent_id','=',0)
->get();
Output:
+-----------------+--------------------------+------------------+-----------------+
|c1_id| c1_name | c2_id| c2_name | c3_id| c3_name | c4_id| c4_name |
+-----------------+--------------------------+------------------+-----------------+
| 1 | ELECTRONICS | 2 | TELEVISIONS | 3 | TUBE | NULL |
| 1 | ELECTRONICS | 2 | TELEVISIONS | 4 | LCD | NULL |
| 1 | ELECTRONICS | 2 | TELEVISIONS | 5 | PLASMA | NULL |
| 1 | ELECTRONICS | 6 | PORTABLE ELECTRONICS | 7 | MP3 PLAYERS | 8 | FLASH |
| 1 | ELECTRONICS | 6 | PORTABLE ELECTRONICS | 9 | CD PLAYERS | NULL |
| 1 | ELECTRONICS | 6 | PORTABLE ELECTRONICS | 10| 2 WAY RADIOS | NULL |
+-------------+--------------------------------------+--------------+-------+
Then, Put $categories
values in an Array
.
$all_categories = [];
$category_c1_id = '';
$category_c2_id = '';
$category_c3_id = '';
$category_c4_id = '';
$c1_id = -1;
$c2_id = -1;
$c3_id = -1;
$c4_id = -1;
foreach ($categories as $k=>$category){
if($category->c1_id != $category_c1_id){
$c1_id = $c1_id +1;
$all_categories[$c1_id]['id'] = $category->c1_id;
$all_categories[$c1_id]['name'] = $category->c1_name;
$c2_id = -1;
}
if($category->c2_id != $category_c2_id && $category->c2_id <> NULL){
$c2_id = $c2_id +1;
$all_categories[$c1_id]['children'][$c2_id]['id'] = $category->c2_id;
$all_categories[$c1_id]['children'][$c2_id]['name'] = $category->c2_name;
$c3_id = -1;
}
if($category->c3_id != $category_c3_id && $category->c3_id <> NULL){
$c3_id = $c3_id +1;
$all_categories[$c1_id]['children'][$c2_id]['children'][$c3_id]['id'] = $category->c3_id;
$all_categories[$c1_id]['children'][$c2_id]['children'][$c3_id]['name'] = $category->c3_name;
$c4_id = -1;
}
if($category->c4_id != $category_c4_id && $category->c3_id <> NULL){
$c4_id = $c4_id +1;
$all_categories[$c1_id]['children'][$c2_id]['children'][$c3_id]['children'][$c4_id]['id'] = $category->c4_id;
$all_categories[$c1_id]['children'][$c2_id]['children'][$c3_id]['children'][$c4_id]['name'] = $category->c4_name;
}
$category_c1_id = $category->c1_id;
$category_c2_id = $category->c2_id;
$category_c3_id = $category->c3_id;
$category_c4_id = $category->c4_id;
}
return $all_categories;
Output:
$categories = [
['id' => 1, 'name' => 'TV & Home Theather'],
['id' => 2, 'name' => 'Tablets & E-Readers'],
['id' => 3, 'name' => 'Computers', 'children' => [
['id' => 4, 'name' => 'Laptops', 'children' => [
['id' => 5, 'name' => 'PC Laptops'],
['id' => 6, 'name' => 'Macbooks (Air/Pro)']
]],
['id' => 7, 'name' => 'Desktops'],
['id' => 8, 'name' => 'Monitors']
]],
['id' => 9, 'name' => 'Cell Phones']
];
Now Display on Select option on Product upload.
<div class="form-group">
<label>Select Categories</label><br/>
@foreach($categories as $category)
@php($category = (object)$category)
<div class="form-check">
<label class="form-check-label" for="{{$category->id}}">
{{ Form::checkbox('category_ids[]', $category->id, null, array('id'=>$category->id)) }}
{{$category->name}}
</label>
@if(isset($category->children))
@foreach($category->children as $subcategory)
@php($subcategory = (object)$subcategory)
<div class="form-check" style="margin-left: 15px;">
<label class="form-check-label" for="{{$subcategory->id}}">
{{ Form::checkbox('category_ids[]', $subcategory->id, null, array('id'=>$subcategory->id)) }}
{{$subcategory->name}}
</label>
@if(isset($subcategory->children))
@foreach($subcategory->children as $subsubcategory)
@php($subsubcategory = (object)$subsubcategory)
<div class="form-check" style="margin-left: 15px;">
<label class="form-check-label" for="{{$subsubcategory->id}}">
{{ Form::checkbox('category_ids[]', $subsubcategory->id, null, array('id'=>$subsubcategory->id)) }}
{{$subsubcategory->name}}
</label>
</div>
@endforeach
@endif
</div>
@endforeach
@endif
</div>
@endforeach
</div>
And ON Menu Option
<ul class="nav primary clone-main-menu toggle-slide-menu" id="mercado_main" data-menuname="Main menu" >
@foreach($categories as $category)
<li class="menu-item menu-item-has-children item-megamenu" >
<a href="#" title="Digital & Electronics" class="link-term mercado-item-title">{{$category['name']}}</a>
<div class="wrap-megamenu">
<div class="megamenu-content min-height-510 bg-vertical-digital">
@if(isset($category['children']))
<div class="row">
@foreach($category['children'] as $subcategory)
<div class="col-lg-3 col-md-3">
<div class="wrap-vertical-nav">
<h2 class="menu-title"><a href="#" class="link-term">{{$subcategory['name']}}</a></h2>
@if(isset($subcategory['children']))
<ul>
@foreach($subcategory['children'] as $subcategory)
<li class="menu-item"><a href="#" class="link-term">{{$subcategory['name']}}</a></li>
@endforeach
</ul>
@endif
</div>
</div>
@endforeach
</div>
@endif
</div>
</div>
</li>
@endforeach
</ul>
Using Eloquent you can use a hasMany()
relationship to relate the table to itself.
Try creating a new method on your model, like so:
class Category extends Eloquent
{
...
public function children()
{
return $this->hasMany('Category','ParentId');
}
}
Then you should be able to get a list of sub categories for any given ID.
$categories = Category::where('ID','=','1')->with('children')->get();
Alternatively, the query suggested by deczo in the comments is a lot simpler, I would recommend using this instead.
Category::with('children')->find(1);