Abaij
Abaij

Reputation: 873

Nested sub category right under parent category in codeigniter

I want to to display the list of category in a table and the sub category of each parent category right under.

EDIT

I want it look like this:

Category One

-> Sub category One #1

-> Sub category One #2

Category Two

-> Sub category Two #1

-> Sub category Two #2

Category Three

-> Sub category Three #1

-> Sub category Three #2

But what I got is:

Category One

Category Two

Category Three

-> Sub category One #1

-> Sub category One #2

-> Sub category Two #1 ... etc

Here is the model:

function get_categories() {
    $data = array();
    $this->db->group_by('parent_id,category_id');
    $query = $this->db->get('category');
    if ($query->num_rows() > 0) {
        foreach ($query->result() as $row) {
            $data[] = $row;
        }
    }
    return $data;
}

And in the controller I call this function with $data['categories']=$this->category_model->get_categories(). And I display the data in the view with this code:

<?php foreach ($categories as $cat) : ?>
   <tr>
      <td><?php echo $cat->name ?></td>
      <td><?php echo $cat->description ?></td>
   </tr>
<?php endforeach; ?>

But the problem is, instead of under each their parent category, the sub categories are all showing on the bottom of the list. Please help me to fix this problem. Thanks.

Upvotes: 2

Views: 6458

Answers (3)

freegovtjobs
freegovtjobs

Reputation: 1

Database should like this

In Model

//categories
public function getCategories()
{
    $query = $this->db->query('select * from categories where cat_parent=0');
    return $query->result_array();
}

public function getCategoriesSub($parent)
{
    $query = $this->db->query("select * from categories where cat_parent='$parent'");
    return $query->result_array();
}

in Controller

public function categories()
{
    $data['mcats'] = $this->admin_model->getCategories();

    foreach($data['mcats'] as $key =>$val){
        $subcats = $this->admin_model->getCategoriesSub($val['cid']);
        if($subcats){
            $data['scats'][$val['cid']] = $subcats;
        }
    }


    $this->load->view('admin/header');
    $this->load->view('admin/category_list', $data);
    $this->load->view('admin/footer');

}

in View

<ul>
<?php 
foreach ($mcats as $key =>$val)
    {
?>
<li><?php echo $val['cat_name']; ?>
<ul>
<?php
    foreach ($scats[$val['cid']] as $sub)  {
        echo '<li>' . $sub['cat_name'] . '</li>';
    }
?>
</ul>
</li>
<?php
}
?>
</ul>

its working code. try this

Upvotes: 0

joni jones
joni jones

Reputation: 2995

You need iterate your categories and group them by parent id. As i understand your categories are stored as Adjacency List, so maybe this example will be helpfull:

function get_categories(){
    $this->db->order_by('parent_id');
    return $this->db->get('category')->result_array();
}
$categories = get_categories();
$result = array();
foreach($categories as $cat){
    if($cat['parent_id'] && array_key_exists($cat['parent_id'], $result)){
        $result[$cat['parent_id']]['sub_categories'][] = $cat;
    }
    else{
        $result[$cat['id']] = $cat;
    }
}

Second step need to render html:

<?php foreach ($result as $cat):?>
    <tr>
         <td><?=$cat['name'];?></td>
         <td><?=$cat['description'];?></td>
    </tr>
    <?php if(isset($cat['sub_categories'])):?>
        <?php foreach($cat['sub_categories'] as $sub_category):?>
            <tr>
                <td><?=$sub_category['name'];?></td>
                <td><?=$sub_category['description'];?></td>
           </tr>
        <?php endforeach;?>
    <?php endif;?>
<?php endforeach;?>

Html output is very similar to @scrowler answer.

Upvotes: 2

scrowler
scrowler

Reputation: 24406

So you're retrieving all the categories correctly, but they aren't displaying correctly. Your problem is that you're looping through all the categories and you aren't correctly outputting the relevant sub categories to the parents. I don't know what your data structure is like, but you must have a foreign key type field somewhere that you can check.

Here's an example of how it should work:

<?php foreach ($categories as $cat) : ?>
    <tr>
       <td><?php echo $cat->name ?></td>
       <td><?php echo $cat->description ?></td>
    </tr>
    <?php foreach($sub_categories as $sub_category) : ?>
        <?php 
        // if this sub_category doesn't belong to the current parent, skip it
        if($sub_category['parent_id'] != $cat['category_id'])
            continue; 
        ?>
        <tr>
            <td><?php echo $sub_category->name ?></td>
            <td><?php echo $sub_category->description ?></td>
        </tr>
    <?php endforeach; ?>
<?php endforeach; ?>

Of course, the better way to do this would be to obtain your data in the correct structure to begin with, e.g. nested array Parent => array(parent_data, Children => array(children_data)).

Upvotes: 2

Related Questions