PHP 树实现:在递归循环上定义父引用

发布于 2024-08-22 22:07:56 字数 3701 浏览 3 评论 0原文

回到我的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

美人骨 2024-08-29 22:07:56

您在递归调用中提供的 $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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文