1

I am making a module for creating navigation menus and I would like to give the possibility to set an initial and final level. I have this array tree with level how can return it setting a start level and stop level ? this is my function that return empty.

Original Array:

Array
(
    [0] => Array
        (
            [id] => 22
            [pid] => 12
            [level] => 0
            [children] => 
        )

    [1] => Array
        (
            [id] => 24
            [pid] => 12
            [level] => 0
            [children] => Array
                (
                    [0] => Array
                        (
                            [id] => 27
                            [pid] => 24
                            [level] => 1
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 28
                                            [pid] => 27
                                            [level] => 2
                                            [children] => 
                                        )

                                )

                        )

                )

        )

    [2] => Array
        (
            [id] => 25
            [pid] => 12
            [level] => 0
            [children] => 
        )

    [3] => Array
        (
            [id] => 26
            [pid] => 12
            [level] => 0
            [children] => 
        )

)

My function:

function get_tree_limit ($pages, $start_level, $stop_level) {

    $result = Array();

    foreach( $pages as $page ) {

        $children = Array();

        if(isset($page['children'])){
            $children = get_tree_limit ($page['children'], $start_level, $stop_level);
        }

        if($page['level'] >= $start_level && $page['level'] <= $stop_level){

            $result[] = Array(
                'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'],
                'children' => $children
            );

        }

    }

    return $result;

}

if I try:

$rpage = get_tree_limit ($pages, 1, 2);
print_r($rpage);

The result is empty:

Array()

Where I am wrong ?

Thanks.

5
  • The problem is that at level 0, although you set $children - you never add this anywhere to be returned. Commented Nov 30, 2019 at 12:50
  • @NigelRen that should return the array empty if no children. If I remove the condition start and stop level return correct. But of coarse my concept is wrong or I solved my self. Can you write the correct fuction or difficult to understand. Thanks. Commented Nov 30, 2019 at 13:02
  • what is in $pages? Commented Nov 30, 2019 at 13:08
  • @ShringirajDewangan $pages of coarse is the original array you can see at the top of the post. Commented Nov 30, 2019 at 13:09
  • Scope of $result variable is in function only and return value is only for key 0 and your start level is 1 Commented Nov 30, 2019 at 15:36

2 Answers 2

1

During simple foreach loop you need to check the main index children and in case of it has array datatype you need to turn on recursive action (use is_array($page['children'])):

if(is_array($page['children'])){ } else {  }

In case of non-array you can just append this values to the result array if the level is in range:

if(   $page['level'] >= $start_level 
   && $page['level'] <= $stop_level 
   && is_numeric($page['level'])
  ){
     $result[$ind] = Array(
                        'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'], 
                        'children' => $page['children']
     ); 
} 

In case of array datatype you need to do the same, but with recursive action:

if(  $page['level'] >= $start_level 
  && $page['level'] <= $stop_level 
  && is_numeric($page['level'])){ 

  $result[$ind] = Array(
                        'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'], 
                        'children' => @get_tree_limit($page, $start_level, $stop_level)['children'] 
  );   
}

if (!isset($result[$ind]) ) {
    if (@count(get_tree_limit($page, $start_level, $stop_level)['children'])>0){
        $result[$ind] = @get_tree_limit($page, $start_level, $stop_level)['children'];
    }
} 

@ hides warnings, so the result body of the function looks like next:

$result = Array();

foreach($pages as $ind => $page ) {

        if(is_array($page['children'])){ 

           if($page['level'] >= $start_level 
           && $page['level'] <= $stop_level 
           && is_numeric($page['level'])){ 
                //print_r($page);
                $result[$ind] = Array(
                    'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'], 
                    'children' => @get_tree_limit($page, $start_level, $stop_level)['children'] 
                );   
            }

            if (!isset($result[$ind]) ) {
               if (@count(get_tree_limit($page, $start_level, $stop_level)['children'])>0){
                    $result[$ind] = @get_tree_limit($page, $start_level, $stop_level)['children'];
               }
            } 

        } else {
            if($page['level'] >= $start_level && $page['level'] <= $stop_level && is_numeric($page['level'])){
                $result[$ind] = Array(
                    'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'], 
                    'children' => $page['children']
                ); 
            } 
        } 
}

return $result;  

For example, $res = get_tree_limit($ar, 2, 3); returns only 2 and 3 levels of the tree:

Array
(
    [0] => Array
        (
            [id] => 28
            [pid] => 27
            [level] => 2
            [children] => Array
                (
                    [id] => 29
                    [pid] => 28
                    [level] => 3
                    [children] => 2
                )

        )

)

Demo

You can choose any level range and you'll get correspond tree branch.

Sign up to request clarification or add additional context in comments.

17 Comments

Your code does its job and looks very clean. Compliments! I've always said that programmers should write code and avoid words :) Thanks
testing your code I check that there is a small problem. if Start or Stop limit is 0 should be ignored. What I mean if you set start_level = 2 and stop_level = 0 should show level 2, 3. same start level 0 stop level 2 should show level 0,1,2. is start_level=0 and stop_level=0 should to show 0,1,2,3.
@DaebakDo, no, it works as a range - you can choose from level to level. 0-0 - gives 0 levels, 0-1 - gives first 2, 1-2 - gives 1 and 2
If you wanna I can fix this with your wishes.
thanks you are really kind. By the way if children doesn't exist return error. For this my code was so long :D
|
0

Ok this function does its job and I insert if someone is looking for it and to receive some suggestions. I also added the control in the case start and stop are null.

function get_tree_limit ($pages, $start_level, $stop_level) {

    $result = Array();

    foreach($pages as $page) {

        $children = Array();

        if(isset($page['children'])){
            $children = get_tree_limit ($page['children'], $start_level, $stop_level);
        }

        if($start_level > 0 && $stop_level > 0){

            if(!empty($children)){

                if($page['level'] >= $start_level && $page['level'] <= $stop_level){

                    $result[] = Array(
                        'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'], 'children' => $children
                    );

                } else {

                    $result = $children;

                }

            } else {

                if($page['level'] >= $start_level && $page['level'] <= $stop_level){

                    $result[] = Array(
                        'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level']
                    );

                }

            }

        } elseif($start_level <= 0 && $stop_level > 0) {

            if(!empty($children)){

                if($page['level'] <= $stop_level){

                    $result[] = Array(
                        'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'], 'children' => $children
                    );

                } else {

                    $result = $children;

                }

            } else {

                if($page['level'] <= $stop_level){

                    $result[] = Array(
                        'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level']
                    );

                }

            }

        } elseif($start_level > 0 && $stop_level <= 0) {

            if(!empty($children)){

                if($page['level'] >= $start_level){

                    $result[] = Array(
                        'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'], 'children' => $children
                    );

                } else {

                    $result = $children;

                }

            } else {

                if($page['level'] >= $start_level){

                    $result[] = Array(
                        'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level']
                    );

                }

            }

        } else {

            if(!empty($children)){

                $result[] = Array(
                    'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level'], 'children' => $children
                );

            } else {

                $result[] = Array(
                    'id' => $page['id'], 'pid' => $page['pid'], 'level' => $page['level']
                );              

            }

        }

    }

    return $result;

}

test

http://sandbox.onlinephpfunctions.com/code/4e9b1822d294f0af65f81a8ad9ce5f61db7e43f7

5 Comments

why if I pass the array and debug all the ase return me the correct array.
@AksenP you can test here sandbox.onlinephpfunctions.com/code/…
And what? 0 to 0 gives 0 to 2 :D You're failed.
@AksenP Change it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.