递归循环 returns 500 内部服务器错误
Recursive looping returns 500 Internal Server Error
在循环中调用递归时出现 500 内部服务器错误。直到那时我才收到 500 错误。
当我删除循环中的递归时,一切正常:
代码:
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;
}
您的代码有一个无限递归循环,导致您的脚本在递归达到 PHP 为递归深度设置的限制时被 PHP 终止。
使用同一组参数一次又一次地调用此代码:
$children = $this->buildReferalsTree($referals, $parentID);
为了终止递归函数,应该有一个条件来定义递归何时结束,我在你的代码中没有看到。
您需要为父参数传递一个新值,而不是一遍又一遍地使用相同的值。像这样:
$children = $this->buildReferalsTree($referals, $item['user_id']);
然后在循环中您还需要按父 ID 进行过滤:
if($item['refered_by'] = $parentID)
...所以您只会 link 属于该 ID "children" 的项目。
此外,您的原始调用还应指定 parentID,因为您 select 只有 table:
的特定 referred_by
子集
$list = $this->buildReferalsTree($referals->result_array(), $userID);
然而,这将给出一个无趣的结果,因为您只 selected 具有 相同 referred_by
值的记录,所以没有太多可从中构建一棵树。相反,您可以 select 来自该 table 的所有记录,然后仍然将 $userID
传递给 buildReferalsTree
,这样所有其他记录都可用于遵循推荐链。所以这里是 select 所有记录的代码:
$sql = "SELECT user_id, username, refered_by FROM users";
$referals = $this->db->query($sql);
最后,内部 if
块中也存在错误,您当前将空数组分配给 $item['children']
。您应该改为分配递归调用的结果,如下所示:
if($children) {
$item['children'] = $children;
}
综上所述,代码如下所示:
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;
}
如果您的数据在引用方面具有循环,这仍然可以提供无限递归。鉴于推荐的含义,但情况不应如此。
正如 Jay Rajput 所说,那里有无限递归。我认为调用
$children = $this->buildReferalsTree($referals, $parentID);
不应传递 $referals
,而是另一个基于 $item
的 'refered_by' 元素构建的数组。
所以基本上你需要创建另一个私有方法,提取新的 $referals
。
您必须仍然意识到这段代码不会容易出错,如果两个项目相互引用,您仍然会以无限递归结束。
您要完成的任务是一个相当大的挑战,尤其是当您使用关系数据库时。您肯定想看看关系数据库中的 'nested set' 概念。
在循环中调用递归时出现 500 内部服务器错误。直到那时我才收到 500 错误。
当我删除循环中的递归时,一切正常:
代码:
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;
}
您的代码有一个无限递归循环,导致您的脚本在递归达到 PHP 为递归深度设置的限制时被 PHP 终止。
使用同一组参数一次又一次地调用此代码:
$children = $this->buildReferalsTree($referals, $parentID);
为了终止递归函数,应该有一个条件来定义递归何时结束,我在你的代码中没有看到。
您需要为父参数传递一个新值,而不是一遍又一遍地使用相同的值。像这样:
$children = $this->buildReferalsTree($referals, $item['user_id']);
然后在循环中您还需要按父 ID 进行过滤:
if($item['refered_by'] = $parentID)
...所以您只会 link 属于该 ID "children" 的项目。
此外,您的原始调用还应指定 parentID,因为您 select 只有 table:
的特定referred_by
子集
$list = $this->buildReferalsTree($referals->result_array(), $userID);
然而,这将给出一个无趣的结果,因为您只 selected 具有 相同 referred_by
值的记录,所以没有太多可从中构建一棵树。相反,您可以 select 来自该 table 的所有记录,然后仍然将 $userID
传递给 buildReferalsTree
,这样所有其他记录都可用于遵循推荐链。所以这里是 select 所有记录的代码:
$sql = "SELECT user_id, username, refered_by FROM users";
$referals = $this->db->query($sql);
最后,内部 if
块中也存在错误,您当前将空数组分配给 $item['children']
。您应该改为分配递归调用的结果,如下所示:
if($children) {
$item['children'] = $children;
}
综上所述,代码如下所示:
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;
}
如果您的数据在引用方面具有循环,这仍然可以提供无限递归。鉴于推荐的含义,但情况不应如此。
正如 Jay Rajput 所说,那里有无限递归。我认为调用
$children = $this->buildReferalsTree($referals, $parentID);
不应传递 $referals
,而是另一个基于 $item
的 'refered_by' 元素构建的数组。
所以基本上你需要创建另一个私有方法,提取新的 $referals
。
您必须仍然意识到这段代码不会容易出错,如果两个项目相互引用,您仍然会以无限递归结束。
您要完成的任务是一个相当大的挑战,尤其是当您使用关系数据库时。您肯定想看看关系数据库中的 'nested set' 概念。