【发布时间】:2013-01-27 12:21:34
【问题描述】:
我有一个代表伪目录系统的 mysql 表:
CREATE TABLE `file_directories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT NULL,
`name` varchar(255) NOT NULL,
`level` int(11) NOT NULL DEFAULT '1',
`created` datetime NOT NULL,
PRIMARY KEY (`name`,`id`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
当用户浏览此系统时,我们的函数会收到一个由name 列中的条目组成的路径。
因此,first/child of first/grandchild 或 second/child of second/grandchild 之类的内容将是有效路径,并且在数据库中看起来像这样。
/----------------------------------------------------\
| id | parent_id | name | level | created |
|----|-----------|-----------------|-------|---------|
| 1 | NULL | First | 1 | ... |
| 2 | 1 | Child of First | 2 | ... |
| 3 | 2 | Grandchild | 3 | ... |
| 4 | NULL | Second | 1 | ... |
| 5 | 4 | Child of Second | 2 | ... |
| 6 | 5 | Grandchild | 3 | ... |
\----------------------------------------------------/
现在,如果我想列出子目录,我的流程是这样的:
$path = 'first/child of first'; // demo data
$path = explode('/', $path); //array('first', 'child of first');
$level = count($path);
$name = end($path);
//query is not actually built like this, it uses the Codeigniter Active Records library
//but this is effectively the end result,
$sql = "SELECT * FROM `file_directories` WHERE `name` = '$name' AND `level` = $level";
///etc
这很好,直到我们处理 grandchild 目录,它们具有相同的名称并存在于同一级别。
目录结构强制只有一个目录可以存在相同的parent_id 和name,但相同的name'd 目录和不同的parent_id 可以存在于相同的level。
我无法更改传递的数据,所以我能想到的唯一方法是从根节点开始,然后循环执行多个查询以找到正确的子节点。
因此,对于 second 的孙子,查询将是。
$parent_id = NULL;
foreach($path as $seg){
$id = SQL: SELECT `id` FROM `file_directories` WHERE `name` = '$seg' AND `parent_id` = (IS NULL for root node) $parent_id;
}
//Get the actual node
$node = SQL: SELECT `*` FROM `file_directories` WHERE `id` = '$id';
但是,有很多查询,所以,在不改变我得到的数据的情况下,有没有更好的方法来跟踪树?还是选择正确的节点?
【问题讨论】:
-
是否强制执行级别数?如果是这样,您可以使用父 ID 自行加入查询。
标签: php mysql recursion tree parent-child