【问题标题】:Retrieve Child Objects检索子对象
【发布时间】:2011-09-02 13:58:47
【问题描述】:

我想要一张这样的 cmets 表

id | comment | parent_id
--------------------------
1    text1        0
2    text2        1
3    text3        2
4    text4        3
5    text5        3
6    text6        5

我想构造一个数组来显示父母和孩子的层次结构。这棵树应该可以追溯到不确定的世代。我不想使用嵌套 foreach 循环,因为我不确定它有多深。这就是我在这里的原因,我不确定此类问题的最佳实践。我还想显示数组中的深度。下面是一个例子。它与上表并没有真正的关系,但希望能让您了解我需要什么。

array(
    "depth"=> 4
    "parent" => array(
        "id"=> 1,
        "comment" => "sometext1"
        "child_count" => 2,
        "children" => array(
            0 => array(
                "id" => 2
                "comment" => "sometext2",
                "child_count" => 0,
                "children" => null
            ),
            1 => array(
                "id" => 3
                "comment" => "sometext3"
                "child_count" => 1,
                "children" => array(
                    0 => array(
                        "id" => 2
                        "comment" => "sometext2",
                        "child_count" => 2,
                        "children" => array(
                            0 => array(
                                "id" => 2
                                "comment" => "sometext2",
                                "child_count" => 0,
                                "children" => null
                            ),
                            1 => array(
                                "id" => 2
                                "comment" => "sometext2",
                                "child_count" => 1,
                                "children" => array(
                                    "id" => 2
                                    "comment" => "sometext2",
                                    "child_count" => 0,
                                    "children" => null
                                )
                            )
                    )
                )
            )
        )
    )
)

我打算使用 foreach 并执行一条 SQL 语句来检索该父/子的孩子。即

$sql = "SELECT * FROM comments WHERE parent = $parent_id";

我并不是真的在寻找所有这些的代码,只是一个伪代码解决方案。

【问题讨论】:

  • 请看一下我的回答,我提供了一种在 PHP 上执行此操作的超级简单的方法。实际上效果很好。
  • 你太棒了。谢谢。我确实很欣赏@Layke 方法,但可能需要我一点时间来理解它。同时我会接受你的回答。

标签: php multidimensional-array


【解决方案1】:

这可以在 PHP 中轻松完成...为此,您需要两个 数组 和两个 while 循环。

此代码将按照您想要的方式创建一棵树,并为未确定的深度和子级数量。

Pastebin to the working code.

使用引用,让我们假设所有内容都保存在具有以下结构的数组 $data 中:(id, comment, parent_id) 其中 parent_id 指向 id .

构建树的代码。

$tree = array();
reset($data);
while (list($k, $v) = each($data))
    if (0 == ($pid = $v['parent_id']))
        $tree[$k] =& $data[$k]; else
        $data[$pid]['children'][$k] =& $data[$k];

并生成深度和子数。

reset($data);
while (list($k, $v) = each($data))
    if (0 != $v['parent_id'])
    {
        $ref =& $data[$k];
        $depth = 0;
        do
        {
            if ($depth) $ref =& $data[$ref['parent_id']];
            $dre =& $ref['depth'];
            if (!isset($dre) || $dre <= $depth) $dre =  $depth++;
            if (isset($ref['children']))
                $ref['child_count'] = count($ref['children']);
                else
            {   
                $ref['child_count'] = 0;
                $ref['children'] = null;
            }   
        }   
        while ($ref['parent_id']);
    }

我所有的代码都是在运行中编写的,甚至没有经过测试,所以如果有任何错误请原谅 meeeeeeeee!!!!!!!!!!!! ← 算了,我试过了它,修复了几个问题,现在完美运行。

注意

要使此代码正常工作,每个项目的索引必须等于其 ID。

我用来试代码的数组。

$data = array(
    '1' => array('id' => '1', 'comment' => 'a', 'parent_id' => 0),
    '2' => array('id' => '2', 'comment' => 'b', 'parent_id' => 0),
    '3' => array('id' => '3', 'comment' => 'c', 'parent_id' => 1),
    '4' => array('id' => '4', 'comment' => 'd', 'parent_id' => 1),
    '5' => array('id' => '5', 'comment' => 'e', 'parent_id' => 2),
    '6' => array('id' => '6', 'comment' => 'f', 'parent_id' => 2),
    '7' => array('id' => '7', 'comment' => 'g', 'parent_id' => 5),
    '8' => array('id' => '8', 'comment' => 'h', 'parent_id' => 7)
    );

【讨论】:

  • 手动创建密钥的原因/必要性是什么。即数组('1'=> 数组('id' ?
  • 因为如果它们不匹配,我在爬上树枝时所做的引用会引用父 ID 减去一个。除了错误之外,它们可能很容易陷入无限迭代中,这会冻结脚本。
  • 如何遍历树数组输出其内容。
  • 对此提出一个新问题,如果没有人先回答,我会回答。 ;)
【解决方案2】:

当您使用邻接列表尝试检索层次结构中的所有子节点时,就会出现此问题。如果您使用 mysql,它只是不能很好地处理递归。 (甲骨文是另一回事)。

创建结构很简单,您现在不应该真正关心如何创建数组结构,首先您想尝试创建一个高效的查询和高效的模型,以完美地适应您将要成为的查询类型制造。

例如,您说要检索所有子节点。那么您可能应该使用nested set models 来代替adjacency list 或在adjacency list 之外使用。

看看其中的一些资源...

Is there a simple way to query the children of a node?

嵌套集的想法是存储节点的lftright 边缘值,这意味着检索任何子节点非常简单,因为您只需选择具有lft 的节点值大于目标节点lft 值,并且小于rgt 值。

检索结果集后,创建数组结构将毫不费力。

请看这里:http://en.wikipedia.org/wiki/Nested_set_model

获得结果后,请看一下我大约一年前提出的这个问题,这正是您想要的。 PHP > Form a multi-dimensional array from a nested set model flat array

示例

id | comment | parent_id  |   lft    |    rgt   |
-------------------------------------------------
1    World        null         1           12
2    Europe        1            2           11
3    England       2            3           10
4    Kent          3            4           5
5    Devon         3            6           9
6    Plymouth      5            7           8

【讨论】:

  • 谢谢莱克。对于您首先链接的嵌套集模型问题答案。你能给我一个该解决方案的架构示例吗?试图把我的头绕过去。
猜你喜欢
  • 1970-01-01
  • 2018-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多