Search code examples
phpselecthierarchicalmulti-level

Restricting the number of times a function recurses in php codeigniter


I want to generate a multilevel hierarchical select option to select parent or any of its child categories in codeigniter. I want to limit the hierarchy level to 3. i.e the option must show parent, its first level child and its second level child with child category indented to the right of parent. I've no problem going through all the hierarchy level. But I can't generate the select option upto a particular hierarchy level. Three levels of hierarchy is what I need in my case. Can anyone please help me.

Here is what I tried so far:

<?php
$category = $this->get_category();

function get_category() {
    $this->db->order_by('parent_id', 'DESC');
    $this->db->select('id, name, parent_id');
    return $this->db->get('tbl_job_category')->result_array();
}

/*
*$category contains the following json data obtained from DB
$category = [{"id":"20","name":"MVC","parent_id":"16"},
{"id":"16","name":"Spring","parent_id":"14"},
{"id":"12","name":"Car Driver","parent_id":"13"},
{"id":"6","name":"Electrical","parent_id":"5"},
{"id":"3","name":"Civil","parent_id":"5"},
{"id":"14","name":"java","parent_id":"2"},
{"id":"15","name":"javascript","parent_id":"2"},
{"id":"17","name":"Computer Operator","parent_id":"1"},
{"id":"2","name":"Programming","parent_id":"1"},
{"id":"4","name":"Networking","parent_id":"1"},
{"id":"11","name":"Hardware","parent_id":"1"},
{"id":"13","name":"Driver","parent_id":"0"},
{"id":"5","name":"Engineering","parent_id":"0"},
{"id":"19","name":"Economics","parent_id":"0"},
{"id":"1","name":"Information Technology","parent_id":"0"}];
*/

$category_options = $this->multilevel_select($category);

function multilevel_select($array,$parent_id = 0,$parents = array()) {
    static $i=0;
    if($parent_id==0)
    {
        foreach ($array as $element) {
            if (($element['parent_id'] != 0) && !in_array($element['parent_id'],$parents)) {
                $parents[] = $element['parent_id'];
            }
        }
    }

    $menu_html = '';
    foreach($array as $element){
        if($element['parent_id']==$parent_id){
            $menu_html .= '<option>';
            for($j=0; $j<$i; $j++) {
                $menu_html .= '&mdash;';
            }
            $menu_html .= $element['name'].'</option>';
            if(in_array($element['id'], $parents)){
                $i++;
                $menu_html .= $this->multilevel_select($array, $element['id'], $parents);
            }
        }
    }
    $i--;
    return $menu_html;
}

echo $category_options;

Solution

  • Limiting the recursion involves three steps :

    • Initializing a counter variable passed as parameter to the recursive function.
    • Testing the counter value against the desired boundary prior to recursing
    • Passing an incremented counter value in case of recursive call.

    In your case that would be the $level variable below :

    function multilevel_select($array,$parent_id = 0,$parents = array(), $level=0) {
        // ....
                if(in_array($element['id'], $parents) && $level < 2){ // your boundary here, 2 for third nesting level from root
    
                    $i++;
                    $menu_html .= $this->multilevel_select($array, $element['id'], $parents, $level+1);
                }
    
            }
        }
        $i--;
        return $menu_html;
    }