|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
到现在,对排版还是不很熟练,经常会排不好。 1 Food 18
|
+---------------------------------------+
| |
2 Fruit 11 12 Meat 17
| |
+------------------------+ +---------------------+
| | | |
3 Red 6 7 Yellow 10 13 Beef 14 15 Pork 16
| |
4 Cherry 5 8 Banana 9
如许全部树状布局可以经由过程摆布值来存储到数据库中。持续之前,咱们看一看上面收拾整顿过的数据表。
+-----------------------+-----+-----+
| parent | name | lft | rgt |
+-----------------------+-----+-----+
| | Food | 1 | 18 |
| Food | Fruit | 2 | 11 |
| Fruit | Red | 3 | 6 |
| Red | Cherry | 4 | 5 |
| Fruit | Yellow | 7 | 10 |
| Yellow | Banana | 8 | 9 |
| Food | Meat | 12 | 17 |
| Meat | Beef | 13 | 14 |
| Meat | Pork | 15 | 16 |
+-----------------------+-----+-----+
注重:因为"left"和"right"在 SQL中有特别的意义,所以咱们需求用"lft"和"rgt"来暗示摆布字段。 别的这类布局中不再需求"parent"字段来暗示树状布局。也就是 说上面如许的表布局就足够了。
+------------+-----+-----+
| name | lft | rgt |
+------------+-----+-----+
| Food | 1 | 18 |
| Fruit | 2 | 11 |
| Red | 3 | 6 |
| Cherry | 4 | 5 |
| Yellow | 7 | 10 |
| Banana | 8 | 9 |
| Meat | 12 | 17 |
| Beef | 13 | 14 |
| Pork | 15 | 16 |
+------------+-----+-----+
好了咱们如今可以从数据库中获得数据了,例如咱们需求失掉"Fruit"项下的一切一切节点就能够如许写查询语句: SELECT * FROM tree WHERE lft BETWEEN 2 AND 11; 这个查询失掉了以下的了局。
+------------+-----+-----+
| name | lft | rgt |
+------------+-----+-----+
| Fruit | 2 | 11 |
| Red | 3 | 6 |
| Cherry | 4 | 5 |
| Yellow | 7 | 10 |
| Banana | 8 | 9 |
+------------+-----+-----+
看到了吧,只需一个查询就能够失掉一切这些节点。为了可以像下面的递归函数那样显示全部树状布局,咱们还需求对如许的查询停止排序。用节点的左值停止排序:
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 ORDER BY lft ASC;
剩下的成绩若何显示层级的缩进了。
<?php
function display_tree($root)
{
// 失掉根节点的摆布值
$result = mysql_query('SELECT lft, rgt FROM tree '.'WHERE name="'.$root.'";');
$row = mysql_fetch_array($result);
// 筹办一个空的右值仓库
$right = array();
// 取得基础点的一切子孙节点
$result = mysql_query('SELECT name, lft, rgt FROM tree '.
'WHERE lft BETWEEN '.$row['lft'].' AND '.
$row['rgt'].' ORDER BY lft ASC;');
// 显示每行
while ($row = mysql_fetch_array($result))
{
// only check stack if there is one
if (count($right)>0)
{
// 反省咱们是不是应当将节点移出仓库
while ($right[count($right)-1]<$row['rgt'])
{
array_pop($right);
}
}
// 缩进显示节点的称号
echo str_repeat(' ',count($right)).$row['name']."n";
// 将这个节点到场到仓库中
$right[] = $row['rgt'];
}
}
?>
假如你运转一下以上的函数就会失掉和递归函数一样的了局。只是咱们的这个新的函数能够会更快一些,由于只要2次数据库查询。 要获知一个节点的途径就更复杂了,假如咱们想晓得Cherry 的途径就使用它的摆布值4和5来做一个查询。
SELECT name FROM tree WHERE lft < 4 AND rgt > 5 ORDER BY lft ASC;
如许就会失掉以下的了局:
+------------+
| name |
+------------+
| Food |
| Fruit |
| Red |
+------------+
那末某个节点究竟有几何子孙节点呢?很复杂,子孙总数=(右值-左值-1)/2 descendants = (right C left - 1) / 2 不信任?本人算一算啦。用这个复杂的公式,咱们可以很快的算出"Fruit 2-11"节点有4个子孙节点,而"Banana 8-9"节点没有子孙节点,也就是说它不是一个父节点了。
很奇异吧?固然我已屡次用过这个办法,然而每次如许做的时分仍是感应很奇异。
这切实其实是个很好的举措,然而有甚么举措可以帮咱们创立如许有摆布值的数据表呢?这里再引见一个函数给人人,这个函数可以将name和parent布局的表主动转换成带有摆布值的数据表。
<?php
function rebuild_tree($parent, $left) {
// the right value of this node is the left value + 1
$right = $left+1;
// get all children of this node
$result = mysql_query('SELECT name FROM tree '.
'WHERE parent="'.$parent.'";');
while ($row = mysql_fetch_array($result)) {
// recursive execution of this function for each
// child of this node
// $right is the current right value, which is
// incremented by the rebuild_tree function
$right = rebuild_tree($row['name'], $right);
}
// we've got the left value, and now that we've processed
// the children of this node we also know the right value
mysql_query('UPDATE tree SET lft='.$left.', rgt='.
$right.' WHERE name="'.$parent.'";');
// return the right value of this node + 1
return $right+1;
}
?>
固然这个函数是一个递归函数,咱们需求从根节点入手下手运转这个函数来重建一个带有摆布值的树
rebuild_tree('Food',1);
这个函数看上去有些庞杂,然而它的感化和手工对表停止编号一样,就是将平面多层布局的转换成一个带有摆布值的数据表。
PHP的理解是新手最难迈过的一道门槛,不过你应该感到幸运的是PHP已经最大极限的为了新手而努力了,如果你学过其他的语言,也许会觉得PHP的确相当的简单,但是如果你之前什么都没学过,那么阿弥陀佛,硬着头皮琢磨吧。 |
|