Reputation: 5248
I'm getting a 500 Internal server error when recursive is called in loop. Only then I get a 500 error.
When I remove recursive in loop everything work good:
Code:
public function getRecrusiveReferals($userID) {
$sql = "SELECT user_id, username, refered_by FROM users WHERE refered_by = ?";
$referals = $this->db->query($sql, $userID);
$list = $this->buildReferalsTree($referals->result_array());
return $list;
}
private function buildReferalsTree(array $referals, $parentID = 0) {
$data = array();
foreach ($referals as $item) {
if($item['refered_by']) {
$children = $this->buildReferalsTree($referals, $parentID);
if($children) {
$item['children'] = array();
}
}
$data[] = $item;
}
return $data;
}
Upvotes: 1
Views: 998
Reputation: 350252
You'll want to pass a new value for the parent argument, not the same over and over again. Like this:
$children = $this->buildReferalsTree($referals, $item['user_id']);
Then in the loop you need to also filter by the parent ID:
if($item['refered_by'] = $parentID)
... so you will only link items that are "children" of that ID.
Furthermore, your original call should also specify the parentID, since you select only a specific referred_by
subset of your table:
$list = $this->buildReferalsTree($referals->result_array(), $userID);
However, this will give an uninteresting result, since you only selected records with the same referred_by
value, so there is not much to build a tree from. Instead, you could select all records from that table, and then still pass $userID
to buildReferalsTree
which will then have all the other records available for following the chains of referrals. So here is the code to select all records:
$sql = "SELECT user_id, username, refered_by FROM users";
$referals = $this->db->query($sql);
Finally, there is also an error in the inner if
block where you currently assign an empty array to $item['children']
. You should instead assign the result from the recursive call, like this:
if($children) {
$item['children'] = $children;
}
Taking this all together, the code would look like this:
public function getRecrusiveReferals($userID) {
$sql = "SELECT user_id, username, refered_by FROM users";
$referals = $this->db->query($sql);
$list = $this->buildReferalsTree($referals->result_array(), $userID);
return $list;
}
private function buildReferalsTree(array $referals, $parentID = 0) {
$data = array();
foreach ($referals as $item) {
if ($item['refered_by'] == $parentID) {
$children = $this->buildReferalsTree($referals, $item['user_id']);
if($children) {
$item['children'] = $children;
}
}
$data[] = $item;
}
return $data;
}
This could still give an infinite recursion if your data has cycles in terms of referrals. Given the meaning of a referral, this should however not be the case.
Upvotes: 0
Reputation: 700
As Jay Rajput said, you've got infinite recursion there. I think that the call
$children = $this->buildReferalsTree($referals, $parentID);
should pass not the $referals
, but another array, built based on 'refered_by' element of $item
.
So basically you need to create another private method, that extracts new $referals
.
You must be still aware that this code won't be errorprone, and if two items refer each other you will still end with an infinite recursion.
What you're trying to accomplish is quite a challenge, especially when you're using relational database. You definitely would like to look at the 'nested set' concept in relational databases.
Upvotes: 0
Reputation: 1888
Your code has a infinite recursive loop causing your script to be killed by PHP when the recursion reaches the limit set by PHP for the recursion depth.
This code is called again and again with the same set of arguments:
$children = $this->buildReferalsTree($referals, $parentID);
For recursive function to terminate, there should be a condition which should define when the recursion ends, I do not see that in your code.
Upvotes: 1