phpcodeignitermodel-view-controllerhtml-listshierarchical

How to create a dynamic hierarchical HTML list from database query results in CodeIgniter


I have a menu generated dynamically by taking title from the database. I have set the same table for sub pages by adding a column p_id.

And my code looks like this.

private $Section = array();
function _menu($root)
{
    $this->db->select('id,title,p_id');
    $this->db->Where('p_id',$root);
    $this->db->Where('status','active');
    $this->db->Where('type','page');
    $this->db->order_by('sort');
    $query = $this->db->get('pages');
    foreach ($query->result() as $row)
    {
        $this->Section[] = '<ul>';
            $this->Section[] = '<li>';
            $this->Section[] = anchor('site/page/'.$row->id.'#cont_main',$row->title);
            $this->_menu($row->id);
            $this->Section[] = '</li>';
        $this->Section[] = '</ul>';
    }
    $query->free_result();
    return $this->Section;
}

//get menu tree    
function MenuTree()
{
    return $this->_menu(0);
}

In above _menu() if a nav has two or more children then it doesn't display because the source populated by it gives extra </ul> and <ul>. The source looks like this

<ul>
<li><a href="#">menu 1</a>
    <ul>
        <li><a>menu 1 sub1</a></li>
    </ul>
    <ul>
        <li><a>menu 1 sub2</a></li>
    </ul>
</li>
</ul>

While I am assuming to get:

<ul>
<li><a href="#">menu 1</a>
    <ul>
        <li><a>menu 1 sub1</a></li>
        <li><a>menu 1 sub2</a></li>
    </ul>
</li>
</ul>

edited I have to add a menu according to the child element. Image comes in all menus which don't have child too due to extra <ul></ul> if I use ul before the loop. The source looks like this.

<ul>
<li><a href="#">menu 1</a>
    <ul>
        <li><a>menu 1 sub1</a>
            <ul></ul>
        </li>
        <li><a>menu 1 sub2</a></li>
    </ul>
</li>
</ul>

Solution

  • You need to add your ul outside the foreach loop AND make sure that you already have results!

    if ($query->num_rows() > 0) { // we actually have results, open a UL and loop to add the LIs
        $this->Section[] = '<ul>';
        foreach ($query->result() as $row) {