Home > OS >  How to stop a recursive loop when a certain condition is met in PHP
How to stop a recursive loop when a certain condition is met in PHP

Time:12-12

I have an array of the below stucture and I want get the element from the root level to the 3rd level

Array
(
 [0] => Array
  (
   [id] => 1
   [parent_id] => 
   [name] => try 
   [sub_categories] => Array
    (
     [0] => Array
      (
       [id] => 2
       [parent_id] => 1
       [name] => try1
       [sub_categories] => Array
        (
         [0] => Array
          (
           [id] => 3
           [parent_id] => 2
           [name] => try2
           [sub_categories] => Array
            (
             [0] => Array
              (
               [id] => 4
               [parent_id] => 3
               [name] => try3
               [sub_categories] => Array
                (
                 [0] => Array
                  (
   

               [id] => 5
                  [parent_id] => 4
                  [name] => try4
                 )

               )

             )

           )

         )

       )

     )

   )
   
       (
    [1] => Array
     (
      [id] => 6
      [parent_id] => 1
      [name] => try1
      [sub_categories] => Array
       (
        [0] => Array
         (
          [id] => 7
          [parent_id] => 6
          [name] => try2
          [sub_categories] => Array
           (
            [0] => Array
             (
              [id] => 8
              [parent_id] => 7
              [name] => try3
              [sub_categories] => Array
               (
                [0] => Array
                 (
                  [id] => 9
                  [parent_id] => 8
                  [name] => try4
                 )

               )

             )

           )

         )

       )

     )

   )

 )

)
public function getElements( $parent_id = NULL, $level = 0 ) {

    $data = models\Categories::find()->where( ['parent_id'=>$parent_id] )->all();
    $arr = array();
    foreach( $data as $data ) {
        if( $level == 3 ) {
            break;
        }
        //do something
        $countChilds = models\Categories::find()->where( ['parent_id'=>$data->id] )->count();
        if( $countChilds > 0 ){
            $catData['sub_categories'] = $this->getElements( $parent_id = $data->id, $level   );
        }
        $arr[] = $catData;
    }
    return $arr;
}

I tried to add a counter and break out of the loop when the counter gets to 3 but it's not working, so i think since the counter can only work on the immediate sub-categories that is next to the root category and since i want to go down the tree 3 level so the counter isn't working what is the best way to achieve this I'd like my resulting array to out put an array with ID 1,2,3,4 , 6,7,8. element with ID 5,9 should not be printed since they belong to level 4

Any help on this would be appreciated

CodePudding user response:

This should be achievable using a counter

$i = 0;
foreach($data as $item){
    $i  ;
    if($i == 3) {
        break;
    }
}

Or alternatively a for loop

for($i=0; $i<3; $i  ){
}

CodePudding user response:

<?php

public function getElements( $parent_id = NULL, $level = 0 ) {
    if( $level == 3 ) return [];
    $data = models\Categories::find()->where( ['parent_id'=>$parent_id] )->all();
    $arr = array();
    foreach( $data as $data ) {       
        //do something
        $countChilds = models\Categories::find()->where( ['parent_id'=>$data->id] )->count();
        if( $countChilds > 0 ){
            $catData['sub_categories'] = $this->getElements( $parent_id = $data->id, $level   1);
        }
        $arr[] = $catData;
    }
    return $arr;
}

In the above code, I made 2 changes.

  • If $level == 3, then return it instantly. No need to put that in the foreach.
  • It should be $catData['sub_categories'] = $this->getElements( $parent_id = $data->id, $level 1); instead of $level , since the child will have parent level 1 and post increment operator doesn't do that. Also, even $level(pre-increment operation) would be a bad idea since you are modifying the variable even for the next upcoming entries in the foreach loop. So, $level 1 is the correct way.
  • Related