【问题标题】:Building a tree view构建树视图
【发布时间】:2010-01-18 17:30:23
【问题描述】:

我对这个问题有点困惑,我已经考虑了一段时间了。我的数据库中有一个包含任务的表。每个任务都可以通过在 parent_id 字段中保存其主键来拥有一个父任务。我对这些任务的链接深度没有限制。

+-----------+-------+-----+
| Field     | Type  | Key |
+-----------+-------+-----+
| id        | int   | PRI |
| parent_id | int   | MUL |
+-------------------+-----+

没有 parent_id 的任务是一个“项目”,所有任务都可以通过共享父任务分组到任务组中。我现在想用项目的所有后代填充一个 HTML 选择框。

Task 1
  -Task 1.1
  -Task 1.2
    -Task 1.2.1
    -Task 1.2.2
  -Task 1.3
Task 2

我该怎么办?我认为某种递归函数是有序的,但我似乎无法真正弄清楚如何去做。

任何帮助将不胜感激。 :)

【问题讨论】:

  • google“物化路径”:-)

标签: php mysql tree


【解决方案1】:

我强烈建议您阅读这篇关于 storing hierarchical data in a database 的文章。那里讨论了两种算法,根据您的需要,其中任何一种都可能是合适的。

邻接列表模型

这是您目前拥有的。树的每个节点都存储对其父节点的引用,您可以通过选择树的每个级别并遍历节点来递归地确定节点的路径。这实现起来很简单,但缺点是要确定到节点的特定路径,需要递归查询。如果您的树发生大量更改(即写入),这是一个很好的方法,因为动态查找每个节点适用于不断变化的树。如果它的读取量很大,那么您在递归中有一些开销。

修改的前序树遍历

我的最爱,这是一个非常简洁的算法。不是存储对父节点的引用(为了方便起见,无论如何您都可以这样做),而是存储对每个给定节点的“左”和“右”节点的引用。一个节点的整个路径可以在单个选择查询中确定,或者相反,可以在一个节点的所有子节点中确定。该算法更难实现,但它对读取繁重的树有性能优势。缺点是每次移动或添加节点时,都必须重新计算树的整个分支,因此它可能不适合写入大量的数据集。

无论如何,希望这篇文章能给你一些想法。挺好的。

【讨论】:

  • 谢谢。前序树遍历实现起来会很有趣,但我现在在这个项目上太远了,无法切换。我修改了该页面上提供的代码以很好地填充选择。
【解决方案2】:

这是一个如何递归遍历数据库以设置 HTML 表单的示例。它是 zombat 所称的“邻接列表模型”的实现。

它使用两个功能:一个是简单地获取“顶级”元素(项目);和一个递归,以获取给定元素的所有子元素。然后我用它来填充 HTML 表单。

<?php
/**
 * Fetches all the projects and returns them as an array.
 * "Projects" meaning: tasks without a parent.
 * @return array
 */
function getProjects() {
    $sql = "SELECT id FROM tree WHERE parentID IS NULL";
    $result = mysql_query($sql) or die(mysql_error());
    $results = array();
    while($row = mysql_fetch_assoc($result)) {
        $results[] = $row['id'];
    }
    return $results;
}

/**
 * Fetches all tasks belonging to a specific parent.
 * Adds HTML space entities to represent the depth of each item in the tree.
 * @param int $parent_id The ID of the parent.
 * @param array $data An array containing the dat, filled in by the function.
 * @param int $current_depth Indicates the current depth of the recursion.
 * @return void
 */
function getTasks($parent_id, &$data, $current_depth=1) {
    $sql = "SELECT id FROM tree WHERE parentID = {$parent_id}";
    $result = mysql_query($sql) or die(mysql_error());
    while($row = mysql_fetch_assoc($result)) {
        $data[] = str_repeat('&nbsp;', $current_depth) . '- ' . $row['id'];
        getTasks($row['id'], $data, $current_depth + 1);
    }
}


/*
 * Fetch all the data and set it up so it can be used in the HTML
 */
mysql_connect('localhost', 'usr', 'pwd');
mysql_select_db('test');

// Get all the projects, adding a "-" as the initial value of the box.
$projects = array_merge(array('-'), getProjects());

// Fetch the tasks.
// If no project has been selected, just show a "please select"
$tasks = array();
if(isset($_GET['project']) && $_GET['project'] != '-') {
    getTasks($_GET['project'], $tasks);
}
else {
    $tasks = array('Select a project');
}

mysql_close();
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <title>Tree Select Example</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">
        <select name="project" onchange="this.parentNode.submit();">
            <?php
            foreach($projects as $_project) {
                $selected = ($_project == @$_GET['project']) ? ' selected' : '';
                echo "<option value=\"{$_project}\"{$selected}>{$_project}</option>";
            }
            ?>
        </select><br>
        <select name="tasks[]" multiple size="10">
            <?php
            foreach($tasks as $_task) {
                echo "<option value=\"{$_task}\">{$_task}</option>";
            }
            ?>
        </select><br>
        <input type="submit">
    </form>
    <pre><?php print_r($_GET); ?></pre>
</body>
</html>

【讨论】:

    【解决方案3】:

    请使用此功能与您一起创建树形视图 虚线 - 指示器。我为选择框选项做了。

    function display_children($parent, $level) { 
    
        // retrieve all children of $parent 
        $output = "";
        $result = mysql_query('SELECT * FROM treeview_items  WHERE parent_id="'.$parent.'";'); 
        while ($row = mysql_fetch_array($result)) { 
            echo "<option value='".$row['id']."'>".str_repeat('--',$level).$row['name']."</option>" ."<br>"; 
            display_children($row['id'], $level+1); 
        } 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-08
      • 2010-09-24
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多