【问题标题】:Show with php a Genealogy tree stored in Database用 php 显示存储在数据库中的家谱树
【发布时间】:2018-08-19 15:13:29
【问题描述】:

我的数据库 (mysql) 中有一个表,其下一个架构:

-----------------------------
- id  name         parent_id
-----------------------------
- 1   grandfather  NULL
- 2   father       1
- 3   uncle        1
- 4   son          2
- 5   brother      2
- 6   sister       2

我想通过以下方式在我的页面上显示它:

grandfather 
father
son
brother
sister
Uncle

(前序遍历)

这是我找到的最佳解决方案(不起作用)

$sql = "SELECT p1.id, p1.name, p1.parent_id FROM tree p1 ORDER BY p1.id";
$result = $conn->query($sql);

while($row = mysqli_fetch_assoc($result)) {
        arbol($row, $result);
};
function arbol($fila, $result) {
            echo $fila["name"] . "<br>";
            $flag = false;
            while($busqueda = mysqli_fetch_row($result)) {
                if($busqueda[2]==$fila["id"]){
                    $flag = true;
                    break;
                }
            };

            if ($flag){
                foreach ($result as $ruta) {
                    if($ruta["parent_id"]==$fila["id"]){
                        arbol($ruta, $result);
                    };
                };


            } else {
                return;
            }
        };
    };

因此,我第一次遍历到底部,但从未遍历树的其余部分:

Grandfather
parent
son

我做错了什么?或者你有什么建议?

注意:完成后我会有很多“祖父”,这就是为什么会有 while(我会在那里添加一个“parent_id=NULL”条件)。

编辑: 执行此操作后的行结构:

while( $row = mysqli_fetch_assoc( $result)){
    $resguard[] = $row;
}
print_r($resguard);

这是(为清楚起见而格式化):

Array ( 
[0] => Array ( [id] => 1 [name] => Grandfather [parent_id] => ) 
[1] => Array ( [id] => 2 [name] => Parent [parent_id] => 1 ) 
[2] => Array ( [id] => 3 [name] => Uncle [parent_id] => 1 ) 
[3] => Array ( [id] => 4 [name] => Son [parent_id] => 2 ) 
[4] => Array ( [id] => 5 [name] => Brother [parent_id] => 2 ) 
[5] => Array ( [id] => 6 [name] => Sister [parent_id] => 2 ) 
)

【问题讨论】:

  • 欢迎来到 Stack Overflow。好问题。如果您不介意,您可以将数据库查询中的行放入常规数组并发布该结构吗?这消除了似乎工作的 DB 组件,使您的示例更多 minimal and verifiable 并且更容易编写答案。
  • 使用该信息编辑了帖子。感谢您的欢迎,多年来一直使用此页面,但找不到此问题的答案。
  • 谢谢,这比查询对象更容易使用。

标签: php database tree genealogy


【解决方案1】:

这是一个适用于您的数据集并假设原始数据按 id 排序的示例(就像您的查询一样)。我相信要走的路是编写小(er)、简单(r)的函数,将数据转换成树并逐步遍历它。可能会像您一样从数组中进行遍历并一次性打印出来,但是我的大脑目前无法想到好的方法。

function make_tree($data) {
    $tree = [];

    foreach ($data as $node) {
        insert($tree, $node);
    }

    return $tree;
}

function insert(&$root, &$node) {
    if (!$root) {
        $root = $node;
    }
    else if ($root["id"] === $node["parent_id"]) {
        $root["children"][] = $node;
    }
    else if (array_key_exists("children", $root)) {
        foreach ($root["children"] as &$c) {
            if (insert($c, $node)) {
                break;
            }
        }
    }
}

function preorder(&$root) {
    if ($root) {
        yield $root;

        if (array_key_exists("children", $root)) {
            foreach ($root["children"] as $c) {
                yield from preorder($c);
            }
        }
    }
}

$data = [
    ["id" => 1, "name" => "Grandfather", "parent_id" => null],
    ["id" => 2, "name" => "Father", "parent_id" => 1],
    ["id" => 3, "name" => "Uncle", "parent_id" => 1],
    ["id" => 4, "name" => "Son", "parent_id" => 2],
    ["id" => 5, "name" => "Brother", "parent_id" => 2],
    ["id" => 6, "name" => "Sister", "parent_id" => 2]
];

$tree = make_tree($data);

foreach (preorder($tree) as $node) {
    echo $node["name"]."\n";
}

输出:

Grandfather
Father
Son
Brother
Sister
Uncle

【讨论】:

  • 非常感谢,我明天喝完咖啡后要测试一下,我现在搞不定,看起来很干净。我唯一的疑问是,如果我在他的孩子之后指控父亲会发生什么。就像,我有 id=1 的“儿子”和 id=2 的“父亲”。它不会跳过父亲吗?也许通过 parent_id 订购将是解决方案?
  • @MatAleAlbiach 没错——再次查看您的查询,我发现它是按id 而不是parentId 排序的,因此您需要进行更改。如果我遗漏了什么或者这不起作用,请随时告诉我,最好有一个反例,我会更新。
  • 今天测试了一下,基本解决了这个问题。这棵树看起来很棒,但我遇到了另一个问题。它绘制了几乎所有的树,但我有一些人的 parent_id 大于他们父母的 parent_id 的情况。示例:父亲 ID 为 1,祖父 ID 为 100。因此,如果我按父母 ID 订购,则儿子将被跳过。我真的想不出一种方法来解决这个问题以及 Id order 导致的问题......
  • 嗯,如果是复杂依赖关系,您可能需要DAG。它可能涉及,或者可能是一个简单的调整,我必须考虑一下。我对您的反例并不完全清楚,似乎父亲会在祖父之后排成一排,因为它的parent_id 是 100,即 &gt; 祖父 ID(null?)并且能够正确插入。随时使用您的最新代码发布一个新问题,尝试解决您拥有的边缘案例和清晰的示例 - 这可能会使未来更容易解决。
  • 我已经发布了这个问题,它真的很具体,所以如果你看一看,我真的很感激。再次感谢。 stackoverflow.com/questions/51938048/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 2015-06-29
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多