PHP 树实现:在递归循环上定义父引用
回到我的 JaxpTree 对象。该树应该将 MySQL 相关表对转换为遵循以下关系的嵌套树:
/**
* Generates a JaxpTree structure. Parameters are used by the recursive
* function. Normally, they shouldn't be specified.
*
* @param int $parent_id
* @param string $source_table
* @param bool $include_childs
*
* @access public
* @return JaxpTree
* @since 1.0
*/
function CreateTree(
$parent_id = 0,
$source_table = "_NodeTable",
$include_childs = true
)
{
# Copy field names to local variables for shortness.
$pfId = $this->_ParentIdField;
$fId = $this->_IdField;
$fL = $this->_LabelField;
# Determine source table. The iteration begins using NodeTable,
# then, to fetch the items, uses ItemTable.
$source_table = !$source_table ? "_NodeTable" : $source_table;
# Get all rows from the source table.
$rows = $this->{$source_table}->GetById($pfId, $parent_id, true);
# If no rows, no process will be done.
if ($rows)
{
# Iterate through the row list.
foreach ($rows as $r)
{
# Get label and id values.
$label = $r->Columns[$fL]->Value;
$id = $r->Columns[$fId]->Value;
# If this node has childrens...
if ($this->{$source_table}->GetById($pfId, $id) && $include_childs)
{
# Do recursive call using this node as root.
$array[$label] = $this->CreateTree($id);
# If this node has items...
if ($this->_ItemTable->GetById($pfId, $id))
{
# Do recursive call using this node as root
# scanning the item table.
$array[$label]->ItemList = $this->CreateItemList($id);
}
}
else # This node has no child, so there's no need for
# more nested trees.
{
# Create a new TreeNode.
$new_node = new JaxpTreeNode($id);
# Send a JaxpMySqlRow object to the node.
# This will turn the row into node elements.
$new_node->LoadFromMySqlRow($r);
# Store the node.
$array[] = $new_node;
if ($source_table != "_ItemTable")
{
$array[$new_node->Attributes->Get($fL)->Value] = $new_node;
}
# If the node has items...
if ($this->_ItemTable->GetById($pfId, $id))
{
# Do recursive call using this TreeNode as root
# scanning the item table.
$new_node->ItemList = $this->CreateItemList($id);
}
} # End checking for children.
} # End iterating the row list.
} # End checking for rows.
# Return a JaxpTree object, using the array as contents.
return (isset($array)
? new JaxpTree(
$array, null,
($parent_id
? $this->CreateTree($parent_id, "_NodeTable", false)
: null)
)
: false);
} // CreateTree()
当我尝试使用附加父引用返回对象时(参见斜体行),我陷入了无限递归循环并且 PHP 崩溃。
我这里哪里出错了?
Back to my JaxpTree object. The tree is supposed to convert a MySQL related-table pair into a nested tree that follows such relationship:
/**
* Generates a JaxpTree structure. Parameters are used by the recursive
* function. Normally, they shouldn't be specified.
*
* @param int $parent_id
* @param string $source_table
* @param bool $include_childs
*
* @access public
* @return JaxpTree
* @since 1.0
*/
function CreateTree(
$parent_id = 0,
$source_table = "_NodeTable",
$include_childs = true
)
{
# Copy field names to local variables for shortness.
$pfId = $this->_ParentIdField;
$fId = $this->_IdField;
$fL = $this->_LabelField;
# Determine source table. The iteration begins using NodeTable,
# then, to fetch the items, uses ItemTable.
$source_table = !$source_table ? "_NodeTable" : $source_table;
# Get all rows from the source table.
$rows = $this->{$source_table}->GetById($pfId, $parent_id, true);
# If no rows, no process will be done.
if ($rows)
{
# Iterate through the row list.
foreach ($rows as $r)
{
# Get label and id values.
$label = $r->Columns[$fL]->Value;
$id = $r->Columns[$fId]->Value;
# If this node has childrens...
if ($this->{$source_table}->GetById($pfId, $id) && $include_childs)
{
# Do recursive call using this node as root.
$array[$label] = $this->CreateTree($id);
# If this node has items...
if ($this->_ItemTable->GetById($pfId, $id))
{
# Do recursive call using this node as root
# scanning the item table.
$array[$label]->ItemList = $this->CreateItemList($id);
}
}
else # This node has no child, so there's no need for
# more nested trees.
{
# Create a new TreeNode.
$new_node = new JaxpTreeNode($id);
# Send a JaxpMySqlRow object to the node.
# This will turn the row into node elements.
$new_node->LoadFromMySqlRow($r);
# Store the node.
$array[] = $new_node;
if ($source_table != "_ItemTable")
{
$array[$new_node->Attributes->Get($fL)->Value] = $new_node;
}
# If the node has items...
if ($this->_ItemTable->GetById($pfId, $id))
{
# Do recursive call using this TreeNode as root
# scanning the item table.
$new_node->ItemList = $this->CreateItemList($id);
}
} # End checking for children.
} # End iterating the row list.
} # End checking for rows.
# Return a JaxpTree object, using the array as contents.
return (isset($array)
? new JaxpTree(
$array, null,
($parent_id
? $this->CreateTree($parent_id, "_NodeTable", false)
: null)
)
: false);
} // CreateTree()
When I attempt to return the object with the additional parent reference (see italic line), I get caught in an endless recursion loop and PHP crashes.
Where am I going wrong here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您在递归调用中提供的 $parent_id 将始终与第一次调用时使用的 $parent_id 相同,因为据我所知,它没有在代码中的任何地方进行修改。这就是你的问题,你通过一遍又一遍地调用具有相同参数的相同函数来创建无限循环。
The $parent_id you provide in the recursive call will always be the same as the one that was used on your first call, since it's not modified anywhere in your code as far as I see. So that's your problem, you create an infinite loop by calling the same function with the same parameters over and over again.