How to Create Multi Level Category Hierarchy ( Category Tree ) - Codeigniter

How to Create Multi level category hierarchy ( Category Tree ) - codeigniter

The biggest problem in your code was that you were overwriting $rows inside your foreach loop.

Additionally, with a recursive solution, like you've gone for, it's important to keep track of what's been returned from the inner calls to the function/method.

Also, I've added an order by, to make sure the root category appears first.

protected function getCategoryTree($level = 0, $prefix = '') {
$rows = $this->db
->select('id,parent_id,name')
->where('parent_id', $level)
->order_by('id','asc')
->get('categories')
->result();

$category = '';
if (count($rows) > 0) {
foreach ($rows as $row) {
$category .= $prefix . $row->name . "\n";
// Append subcategories
$category .= $this->getCategoryTree($row->id, $prefix . '-');
}
}
return $category;
}

public function printCategoryTree() {
echo $this->getCategoryTree();
}

Facing some issues in multi level category hierarchy

The problem is that your nesting code is referencing nonexistent IDs in $array.

For "tin rasugulla", parent_id = 3, which doesn't exist on the root level of $array so it gets created, when it should in fact try to find the parent with ID 3, which is below "sweets".

This should work:

public function get_nested(){
// fetching categories from table
$this->db->order_by($this->_order_by);
$pages = $this->db->get($this->_table_name)->result_array();

// now creating category tree
foreach ($pages as $page){
if ($page['parent_id'] == 0){
$array[$page['id']] = $page;
} elseif (isset($array[$page['parent_id']])) {
$array[$page['parent_id']]['children'][$page['id']] = $page;
} else {
foreach ($array as $root_id => $parent) {
if (isset($parent['children'][$page['parent_id']])) {
$array[$root_id]['children'][$page['parent_id']]['children'][$page['id']] = $page;
}
}
}
}
return $array;
}

Get all categories (multilevel)

The simplest solution to your problem would be to add recursion.

public function getCategoryTreeForParentId($parent_id = 0) {
$categories = array();
$this->db->from('categories');
$this->db->where('parent_id', $parent_id);
$result = $this->db->get()->result();
foreach ($result as $mainCategory) {
$category = array();
$category['id'] = $mainCategory->id;
$category['name'] = $mainCategory->name;
$category['parent_id'] = $mainCategory->parent_id;
$category['sub_categories'] = $this->getCategoryTreeForParentId($category['id']);
$categories[$mainCategory->id] = $category;
}
return $categories;
}

This approach can be greatly increased in speed by preloading all categories and operating over the array, thus skipping the query for each new parent_id.

Also i did not use the objects of codeigniter, as i don't know them. If they support magic setters / getters or can be convinced to take a array of child objects, they should be used instead the the array i build here.

What the algorithm does is: load all categories with a given parent_id, loop through all those categories, assume the iteration-category-id as parent_id and load everything for it.
This effectively loads all categories, as long as they reference existing categories.

There is a slight danger involved: When you have construct of categories A and B where A has B as parent and B has A as parent, you will run into an endless loop, as they load each other again and again. This forces you to have a clean tree structure in your data.

Update

As this still gets upvotes:
There is another advice concerning this implementation.
If your category tree is bigger or has multiple levels, you might run into performance issues, as this implementation loads the categories again and again with new query parameters. This can quite easily result in dozens, hundreds or thousands of queries, depending on your category tree.

A quite more efficient way is to load all categories (with one query) from your category table and sort them with recursion within your application. This is one of the rare cases, where early evaluation does improve performance.

If the tree is required more than once within the same request, one could even add caching through static variables (with all the usual dangers of caching).

how to display categories,sub categories and sub sub categories - codeigniter

I got the output

public function get_dt_data()
{
error_reporting(1);
// data is loading into $list
$list = $this->category1_model->get_datatables();
$parenrarray=array();

foreach($list as $k){
$parenrarray[$k->category_id]=$k->category_name;
}

//echo '<pre>';print_r($list);echo'</pre>';;
//echo '<pre>';print_r($parenrarray);echo'</pre>';exit();


$data = array();
$no = $_POST['start'];
foreach ($list as $p) {
$no++;
$row = array();

$row[] = "<input type='checkbox' class='deleteRow' value='".$row['category_id']."' /> #".$no ;
$row[] = $p->category_id;

// DISPLAY TABLE HIERARCHY ----
$y=($p->is_parent !=0)?$parenrarray[$p->is_parent]:$p->category_name;
$x=$p->is_child !=0 ?$parenrarray[$p->is_child]:($p->is_parent !=0 ?$p->category_name:'0');
$z=$p->is_child !=0 ?$p->category_name:'0';

$row[] = "<a href='".base_url()."admin/category/level1/$p->category_name'>".$y.'</a>';
$row[] = "<a href='".base_url()."admin/category/level1/$p->category_name'>".$x.'</a>';
$row[] = "<a href='".base_url()."admin/category/level1/$p->category_name'>".$z.'</a>';

// DATA ACTIONS-------
$row[] = '<a class="btn btn-xs btn-primary" href="javascript:void()" title="Edit" onclick="edit_person('."'".$p->category_id."'".')">
<i class="glyphicon glyphicon-pencil"></i> Edit</a>
<a class="btn btn-xs btn-danger" href="javascript:void()" title="Hapus" onclick="delete_person('."'".$p->category_id."'".')">
<i class="glyphicon glyphicon-trash"></i> Delete</a>';
$data[] = $row;

}

$output = array(
"draw" => $_POST['draw'],
"recordsTotal" => $this->categories->count_all(),
"recordsFiltered" => $this->categories->count_filtered(),
"data" => $data,
);
//output to json format
echo json_encode($output);
}


Related Topics



Leave a reply



Submit