1

For example, we are now logged on as user id 10, when our recursion code is executed we get a tree, here:

Level  ID  P_ID
  1    12   10
  1    13   10
  1    14   9
  2    15   12
  2    16   14
  2    17   14
  3    18   17

It should be like this:

 Level  ID  P_ID
  1    12   10
  1    13   10
  2    15   12

Because we are looking from the current id, i.e. for another id the construction logic is the same.

Recursion code:

    $res = $mysql->query("SELECT * FROM table"); 

$data = array();
while($row = mysqli_fetch_assoc($res)){
    $data['spids'][$row['id']]        = $row['sponsor_id'];

    if(isset($data['level'][$row['sponsor_id']])){
        $level = $data['level'][$row['sponsor_id']] + 1;
    } else {
        $level = 0;
    }

    $data['level'][$row['id']] = $level;
}

echo '
<table>
        <tr>
            <td>Level</td>
            <td>ID</td>
            <td>P_ID</td>
        </tr>';
foreach($data['level'] as $id=>$level){
    if ($level != 0) {
    echo '
    <tr>
        <td>'.$level.'</td>
        <td>'.$id.'</td>
        <td>'.$data['spids'][$id].'</td>

    </tr>';
    }
}
echo '
</table>';

Can anyone help how to change part of the function so that the selection of the tree is correct?

Andi Crew
  • 99
  • 1
  • 10
  • 1
    You'll have to explain a bit more about your *expected result*... because if you are looking by id, of 10, why does it return 12 13 15? – IncredibleHat Dec 14 '17 at 14:56
  • It returns these id's because they are childs for id 10, but at different depths. Those, if for "12" child is "15", for "10" it will be(child-child) at a depth: 2 – Andi Crew Dec 14 '17 at 15:00
  • @AndiCrew but ID #25's parent is 12, how does that factor in? why is it included in the expected output, but not other records from level 2? – William Perron Dec 14 '17 at 15:02
  • @WilliamPerron I'm guessing as it bubbles up. The parent of #15 is 12, and the parent of #12 is 10... – IncredibleHat Dec 14 '17 at 15:08
  • @IncredibleHat right, I hadn't noticed that 14's parent was 9 and not 10 – William Perron Dec 14 '17 at 15:10
  • @AndiCrew if you need to have level 1 to only include rows where the parent id is 10, there should probably be a `WHERE` clause in your select statement. – William Perron Dec 14 '17 at 15:13
  • @AndiCrew Is it possible that the `id` is bigger than the `parent id`? Like : Level 1, id 5, p_id 15 – Philipp Maurer Dec 14 '17 at 15:19
  • William Perron, no, if I add `WHERE` it will limit the query to the first level of depth. Philipp Maurer, yes, maybe, although not often found. – Andi Crew Dec 14 '17 at 15:29
  • @AndiCrew not necessarily: check out [this](https://stackoverflow.com/questions/20215744/how-to-create-a-mysql-hierarchical-recursive-query) question – William Perron Dec 14 '17 at 16:23

1 Answers1

1

Here is your recursive process. See inline comments for explanation of steps. I've added your commented table data in place of the query and resultset generation so that I could test my code.

(You'll only need to delete the two hardcoded resultset and uncomment the query and retrieval lines.)

Code: (Demo)

function recursive_search($haystack,$needles,$level=1,&$result=[]){
    foreach($haystack as $k=>$row){
        //echo "\nchecking: {$row['P_ID']} against: ".implode(',',$needles);
        if(in_array($row['P_ID'],$needles)){  // look for qualifying rows
            //echo " found";
            $result[]=array_merge(['Level'=>$level],$row);                   // store qualifying row
            $new_needles[]=$row['ID'];        // store the search value for the next recursive call
            unset($haystack[$k]);             // reduce the haystack to improve efficiency and avoid infinite loop
        }
    }
    if(isset($new_needles)){
        recursive_search($haystack,$new_needles,$level+1,$result);  // recurse as long as there are new needles declared
    }
    return $result;
}

// $res = $mysql->query("SELECT id AS ID, sponsor_id AS P_ID, username AS Name FROM user");
// for($resultset=[]; $row=$res->fetch_assoc(); $resultset[]=$row);  // inspired by: http://php.net/manual/en/mysqli-result.fetch-assoc.php#112924
$resultset=[
    ['ID'=>'0','P_ID'=>NULL,'Name'=>'RMagen'],
    ['ID'=>'1','P_ID'=>NULL,'Name'=>'siokpol'],
    ['ID'=>'2','P_ID'=>NULL,'Name'=>'green'],
    ['ID'=>'3','P_ID'=>NULL,'Name'=>'test12'],
    ['ID'=>'5','P_ID'=>NULL,'Name'=>'Dist'],
    ['ID'=>'7','P_ID'=>NULL,'Name'=>'name'],
    ['ID'=>'8','P_ID'=>NULL,'Name'=>'sas'],
    ['ID'=>'9','P_ID'=>NULL,'Name'=>'dad'],
    ['ID'=>'10','P_ID'=>NULL,'Name'=>'name541'],
    ['ID'=>'11','P_ID'=>'1','Name'=>'ini'],
    ['ID'=>'12','P_ID'=>'9','Name'=>'dad2'],
    ['ID'=>'13','P_ID'=>'9','Name'=>'dad3'],
    ['ID'=>'14','P_ID'=>'9','Name'=>'dad4'],
    ['ID'=>'15','P_ID'=>'9','Name'=>'dad5'],
    ['ID'=>'16','P_ID'=>'9','Name'=>'dad6'],
    ['ID'=>'17','P_ID'=>'12','Name'=>'dad21'],
    ['ID'=>'18','P_ID'=>'12','Name'=>'dad22'],
    ['ID'=>'19','P_ID'=>'12','Name'=>'dad23'],
    ['ID'=>'20','P_ID'=>'12','Name'=>'dad24'],
    ['ID'=>'21','P_ID'=>'13','Name'=>'dad31'],
    ['ID'=>'22','P_ID'=>'13','Name'=>'dad32'],
    ['ID'=>'23','P_ID'=>'13','Name'=>'dad33'],
    ['ID'=>'24','P_ID'=>'14','Name'=>'dad41'],
    ['ID'=>'25','P_ID'=>'14','Name'=>'dad42'],
    ['ID'=>'26','P_ID'=>'14','Name'=>'dad43'],
    ['ID'=>'27','P_ID'=>'17','Name'=>'dad211'],
    ['ID'=>'28','P_ID'=>'17','Name'=>'dad212'],
    ['ID'=>'29','P_ID'=>'17','Name'=>'dad213'],
    ['ID'=>'30','P_ID'=>'18','Name'=>'dad221'],
    ['ID'=>'31','P_ID'=>'18','Name'=>'dad222'],
    ['ID'=>'32','P_ID'=>'18','Name'=>'dad223'],
    ['ID'=>'33','P_ID'=>'27','Name'=>'dad2111'],
    ['ID'=>'34','P_ID'=>'27','Name'=>'dad2112'],
    ['ID'=>'35','P_ID'=>'27','Name'=>'dad2113'],
    ['ID'=>'36','P_ID'=>'30','Name'=>'dad2211'],
    ['ID'=>'37','P_ID'=>'30','Name'=>'dad2212'],
    ['ID'=>'38','P_ID'=>'30','Name'=>'dad2213'],
    ['ID'=>'39','P_ID'=>NULL,'Name'=>'sas2'],
    ['ID'=>'40','P_ID'=>NULL,'Name'=>'sas3'],
    ['ID'=>'42','P_ID'=>'14','Name'=>'dad433']
];

//$idUser = 10; // YIELDS NO RECURSIVE SEARCH RESULTS
$idUser = 1;  // YIELDS ONE RECURSIVE SEARCH RESULT
//$idUser = 9;  // YIELDS MANY RECURSIVE SEARCH RESULTS
$array=recursive_search($resultset,[$idUser]);  // pass `$idUser` as an array element

echo "<table>";
    echo "<tr><td>Level</td><td>ID</td><td>P_ID</td><td>Name</td></tr>";
    foreach($array as $row){
        echo "<tr><td>{$row['Level']}</td><td>{$row['ID']}</td><td>{$row['P_ID']}</td><td>{$row['Name']}</td></tr>";
    }
echo "</table>";

Output:

<table>
    <tr>
        <td>Level</td>
        <td>ID</td>
        <td>P_ID</td>
        <td>Name</td>
    </tr>
    <tr>
        <td>1</td>
        <td>11</td>
        <td>1</td>
        <td>ini</td>
    </tr>
</table>
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • I almost understand the logic of your code, but I can't adapt to my case – Andi Crew Dec 15 '17 at 06:10
  • I don't understand, how it use from db query and output in table. After `(SELECT * ...)query` we put our data in array, like this: `$data = array();` think it's same as your `$array=...` So i tried a couple variations of your code to use with db query, but I didn't get a result on the derivation, only `array()` – Andi Crew Dec 15 '17 at 08:31
  • Ok, I put my current working code: http://sandbox.onlinephpfunctions.com/code/6124551cd7772cb0685830efa445d6fde1abb374 Id you can help me today, it will be great. So in db it's like in my post: id, p_id. Level is not db cell. – Andi Crew Dec 15 '17 at 08:50
  • Ok, thank you, new sandbox didn't work correctly. I'll think about it too. – Andi Crew Dec 15 '17 at 09:20
  • So I tried couple variations, current problem is that `print_f($array)` return empty `array()`, but mysql query is ok. Can't understand why... – Andi Crew Dec 15 '17 at 21:59
  • Yes, it's full. Here it is: http://sandbox.onlinephpfunctions.com/code/c3c3a17443c29caa82736755079bc1073daa6d3e – Andi Crew Dec 15 '17 at 23:43
  • I didn't correctly understand you, id(parent), p_id(child) (p_id is same as sponsor_id, I just simplified for an example), and I have name, qualification too – Andi Crew Dec 16 '17 at 00:04
  • I can add more columns to output, it's not hard . For simplify and chose only `id` and `p_id`, but you can add one more for an example, `name`. In Sandbox is actual output from the database. – Andi Crew Dec 16 '17 at 00:16
  • It's same as `SELECT id as ID, p_id AS P_ID FROM table`. Result by `var_export($resultset) ` I added in Sandbox – Andi Crew Dec 16 '17 at 00:22
  • You can see and make sure that it is similar to the Sandbox array, where the function output `var_export($resultset)` https://imgur.com/a/5CNoH – Andi Crew Dec 16 '17 at 01:13
  • The logic of the code works perfecly. Thank you for your help, and thank you for commenting on the code, with them I understood the logic of the function, I will now study code in more detail. – Andi Crew Dec 16 '17 at 07:40
  • You are welcome. Let's tidy the page by removing comments. – mickmackusa Dec 16 '17 at 07:41