获取修改的预定义树遍历模型(嵌套集)到< ul> [英] Getting a modified preorder tree traversal model (nested set) into a <ul>

查看:105
本文介绍了获取修改的预定义树遍历模型(嵌套集)到< ul>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用树遍历模型将我的数据分层建立到< ul>以便在我的网站上显示。



以下是我的代码:

  function getCats($){ 
//检索$ parent的所有子元素
$ query =SELECT max(rght)as max from t_categories;
$ row = C_DB :: fetchSingleRow($ query);
$ max = $ row [max];
$ result =< ul>;
$ query =SELECT * from t_categories where lft> = 0 and rght< = $ max;
if($ rs = C_DB :: fetchRecordset($ query)){
$ p_right =;
$ p_left =;
$ p_diff =;
while($ row = C_DB :: fetchRow($ rs)){
$ diff = $ row [rght] - $ row [lft];

if($ diff == $ p_diff){
$ result。=< li>。$ row ['title']。< / li>;
} elseif(($ row [rght] - $ row [lft]> 1)&&($ row [rght]> $ p_right)){
$结果。 < UL> 中;
$ result。=< li>。$ row ['title']。< / li>;

} else {
$ result。=< li>。$ row ['title']。< / li>;
}

$ p_right = $ row [rght];
$ p_left = $ row [lft];
$ p_diff = $ diff;
}
}
$ result。=< / ul>;
返回$ result;
}

以下是我的示例表:

  | ID | TITLE | LFT | rght | 
| 1 |猫1 | 1 | 16 |
| 18 | Cat 2 | 3 | 4 |
| 22 | Cat 3 | 5 | 6 |
| 28 | Cat 4 | 7 | 8 |
| 34 | Cat 5 | 9 | 9 |
| 46 |猫6 | 11 | 10 |
| 47 | Cat 7 | 13 | 12 |
| 49 | Cat 8 | 15 | 14 |

现在它输出如下内容:

 < ul> 
< li> Cat 1< / li>
< li> Cat 2< / li>
< li> Cat 3< / li>
< li> Cat 4< / li>
< li> Cat 5< / li>
< li> Cat 6< / li>
< li> Cat 7< / li>
< li> Cat 8< / li>
< / ul>

任何人都可以告诉我为什么或者如何在层次结构中输出列表?



相关主题

解决方案

好吧,让我们做一些赏金狩猎;)

清理示例:

如前所述,您的示例数据已损坏,因为它没有定义有效的嵌套集合。如果你从应用程序中获取这些数据,你应该检查插入/删除逻辑。



因此,为了测试,我使用了如下消毒版本:

(MySQL在这里,因为它是第一手)


  CREATE TABLE t_categories`(
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(45)NOT NULL,
`lft` INTEGER UNSIGNED NOT NULL,
`rght` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
);

INSERT INTO t_categories(title,lft,rght)VALUES('Cat 1',1,16);
INSERT INTO t_categories(title,lft,rght)VALUES('Cat 2',2,3);
INSERT INTO t_categories(title,lft,rght)VALUES('Cat 3',4,7);
INSERT INTO t_categories(title,lft,rght)VALUES('Cat 4',5,6);
INSERT INTO t_categories(title,lft,rght)VALUES('Cat 5',8,13);
INSERT INTO t_categories(title,lft,rght)VALUES('Cat 6',9,12);
INSERT INTO t_categories(title,lft,rght)VALUES('Cat 7',10,11);
INSERT INTO t_categories(title,lft,rght)VALUES('Cat 8',14,15);

第1步 - 让数据库进行排序

嵌套集合主要是作为在数据库中存储树的一种便捷方式发明的,因为它们使查询子树,父关系以及在这种情况下对于顺序和深度的查询变得非常容易:

  SELECT node.title,(COUNT(parent.title) -  1)AS深度
FROM t_categories AS节点
CROSS JOIN t_categories AS parent
WHERE node.lft BETWEEN parent.lft和parent.rght
GROUP BY node.title
ORDER BY node.lft

这将返回您的集合整齐排列,从根节点开始并继续以预先结束的顺序排列。最重要的是,它会将每个节点的深度作为正整数相加,表明该节点在根节点(级别0)以下有多少级别。对于上面的示例数据,结果是:

  title,depth 
'Cat 1',0
'Cat 2',1
'Cat 3',1
'Cat 4',2
'Cat 5',1
'Cat 6',2
'Cat 7',3
'Cat 8',1

  //获取有序数据
$ query ='';
$ query。='SELECT node.title,(COUNT(parent.title) - 1)AS depth';
$ query。='FROM t_categories AS node';
$ query。='CROSS JOIN t_categories AS parent';'
$ query。='WHERE node.lft BETWEEN parent.lft AND parent.rght';
$ query。='GROUP BY node.title';
$ query。='ORDER BY node.lft';

$ result = mysql_query($ query);

//建立数组
$ tree = array();
while($ row = mysql_fetch_assoc($ result)){
$ tree [] = $ row;

$ / code>

结果数组如下所示:

 数组

[0] =>数组

[title] => Cat 1
[depth] => 0


[1] => Array

[title] => Cat 2
[depth] => 1

...

第2步 - 以HTML列表片段形式输出: 使用while循环:

  //引导循环
$ result ='';
$ currDepth = -1; // -1获取外部< ul>
while(!empty($ tree)){
$ currNode = array_shift($ tree);
//降级?
if($ currNode ['depth']> $ currDepth){
//是,打开< ul>
$ result。='< ul>';
}
//升级?
if($ currNode ['depth']< $ currDepth){
//是,关闭n打开< ul>
$ result。= str_repeat('< / ul>',$ currDepth - $ currNode ['depth']);
}
//总是添加节点
$ result。='< li>'。 $ currNode ['title']。 < /立GT;;
//调整当前深度
$ currDepth = $ currNode ['depth'];
//我们完成了吗?
if(empty($ tree)){
//是,关闭n打开< ul>
$ result。= str_repeat('< / ul>',$ currDepth + 1);
}
}

print $ result;

与递归函数相同的逻辑:

<$ p ($ tree,$ currDepth = -1){
$ currNode = array_shift($ tree); $ p> 函数renderTree
$ result ='';
//下线?
if($ currNode ['depth']> $ currDepth){
//是,prepend< ul>
$ result。='< ul>';
}
//往上走?
if($ currNode ['depth']< $ currDepth){
//是,关闭n打开< ul>
$ result。= str_repeat('< / ul>',$ currDepth - $ currNode ['depth']);
}
//总是添加节点
$ result。='< li>'。 $ currNode ['title']。 < /立GT;;
//剩下的东西?
if(!empty($ tree)){
//是,递归
$ result。= renderTree($ tree,$ currNode ['depth']);
}
else {
//否,关闭剩余的< ul>
$ result。= str_repeat('< / ul>',$ currNode ['depth'] + 1);
}
返回$ result;
}

打印renderTree($ tree);

两者都会输出以下结构:

 < UL> 
< li> Cat 1< / li>
< li>
< ul>
< li> Cat 2< / li>
< li> Cat 3< / li>
< li>
< ul>
< li> Cat 4< / li>
< / ul>
< / li>
< li> Cat 5< / li>
< li>
< ul>
< li> Cat 6< / li>
< li>
< ul>
< li> Cat 7< / li>
< / ul>
< / li>
< / ul>
< / li>
< li> Cat 8< / li>
< / ul>
< / li>
< / ul>






Nitpickers角落:Questioner明确要求< ul> ,但是排序了无序列表!来吧......

; - )

I am trying to get my data which is hierarchically set up with a tree traversal model into an < ul> in order to show on my site.

Here is my code:

function getCats($) {
  // retrieve all children of $parent
  $query = "SELECT max(rght) as max from t_categories";
  $row = C_DB::fetchSingleRow($query);
  $max = $row["max"];
  $result ="<ul>";
  $query = "SELECT * from t_categories where lft >=0 and rght <= $max";
  if($rs = C_DB::fetchRecordset($query)){
    $p_right ="";
    $p_left ="";
    $p_diff="";          
    while($row = C_DB::fetchRow($rs)){
      $diff = $row["rght"] -$row["lft"];

      if($diff == $p_diff){
        $result.= "<li>".$row['title']."</li>";
      }elseif (($row["rght"] - $row["lft"] > 1) && ($row["rght"] > $p_right)){
        $result. "<ul>";
        $result.= "<li>".$row['title']."</li>";

      }else{
        $result.= "<li>".$row['title']."</li>";
      } 

      $p_right = $row["rght"];
      $p_left = $row["lft"];
      $p_diff = $diff;
    }
  }
  $result.= "</ul>";
  return $result;
} 

Here is my sample table:

|ID  |  TITLE | lft| rght |
|1   | Cat 1  | 1      |    16       |
|18  | Cat 2  | 3      |    4       |
|22  | Cat 3  | 5      |    6       |
|28  | Cat 4  | 7      |    8       |
|34  | Cat 5  | 9      |    9       |
|46  | Cat 6  | 11      |    10       |
|47  | Cat 7  | 13      |    12       |
|49  | Cat 8  | 15      |    14       | 

Now it outputs something like:

    <ul>
<li>Cat 1</li>
<li>Cat 2</li>
<li>Cat 3</li>
<li>Cat 4</li>
<li>Cat 5</li>
<li>Cat 6</li>
<li>Cat 7</li>
<li>Cat 8</li>
</ul>

Can anyone tell me why or how it will output the list in hierarchical a structure?

Related topic

解决方案

Ok, let's do some bounty hunting ;)

Step 0 - Sanitize example:
As already mentioned, your example data is broken, as it does not define a valid nested set. If you took this data from an app, you should check the insert/delete logic.

So for testing, I used a sanitized version like so:
(MySQL here, as it was the first at hand)

CREATE TABLE t_categories`(
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(45) NOT NULL,
  `lft` INTEGER UNSIGNED NOT NULL,
  `rght` INTEGER UNSIGNED NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 1',1,16);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 2',2,3);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 3',4,7);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 4',5,6);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 5',8,13);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 6',9,12);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 7',10,11);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 8',14,15);

Step 1 - Let the database do the ordering
Nested sets where primarily invented as a convenient way of storing trees in databases, as they make it pretty easy to query for subtrees, parent relations and, especially interesting in this case, for order and depth:

SELECT node.title, (COUNT(parent.title) - 1) AS depth
 FROM t_categories AS node
 CROSS JOIN t_categories AS parent
 WHERE node.lft BETWEEN parent.lft AND parent.rght
 GROUP BY node.title
 ORDER BY node.lft

This will return your set neatly ordered, starting with the root node and continuing to the end in preorder. Most importantly, it will add the depth of each node as a positive integer, indicating how many levels the node is below root (level 0). For the above example data, the result will be:

title, depth
'Cat 1', 0
'Cat 2', 1
'Cat 3', 1
'Cat 4', 2
'Cat 5', 1
'Cat 6', 2
'Cat 7', 3
'Cat 8', 1

In code:

// Grab ordered data
$query = '';
$query .= 'SELECT node.title, (COUNT(parent.title) - 1) AS depth';
$query .= ' FROM t_categories AS node';
$query .= ' CROSS JOIN t_categories AS parent';
$query .= ' WHERE node.lft BETWEEN parent.lft AND parent.rght';
$query .= ' GROUP BY node.title';
$query .= ' ORDER BY node.lft';

$result = mysql_query($query);

// Build array
$tree = array();
while ($row = mysql_fetch_assoc($result)) {
  $tree[] = $row;
}

The resulting array will look like this:

Array
(
    [0] => Array
        (
            [title] => Cat 1
            [depth] => 0
        )

    [1] => Array
        (
            [title] => Cat 2
            [depth] => 1
        )
    ...
)

Step 2 - Output as HTML list fragment:

Using while loop:

// bootstrap loop
$result = '';
$currDepth = -1;  // -1 to get the outer <ul>
while (!empty($tree)) {
  $currNode = array_shift($tree);
  // Level down?
  if ($currNode['depth'] > $currDepth) {
    // Yes, open <ul>
    $result .= '<ul>';
  }
  // Level up?
  if ($currNode['depth'] < $currDepth) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth - $currNode['depth']);
  }
  // Always add node
  $result .= '<li>' . $currNode['title'] . '</li>';
  // Adjust current depth
  $currDepth = $currNode['depth'];
  // Are we finished?
  if (empty($tree)) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth + 1);
  }
}

print $result;

Same logic as recursive function:

function renderTree($tree, $currDepth = -1) {
  $currNode = array_shift($tree);
  $result = '';
  // Going down?
  if ($currNode['depth'] > $currDepth) {
    // Yes, prepend <ul>
    $result .= '<ul>';
  }
  // Going up?
  if ($currNode['depth'] < $currDepth) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth - $currNode['depth']);
  }
  // Always add the node
  $result .= '<li>' . $currNode['title'] . '</li>';
  // Anything left?
  if (!empty($tree)) {
    // Yes, recurse
    $result .=  renderTree($tree, $currNode['depth']);
  }
  else {
    // No, close remaining <ul>
    $result .= str_repeat('</ul>', $currNode['depth'] + 1);
  }
  return $result;
}

print renderTree($tree);

Both will output the following structure:

<ul>
    <li>Cat 1</li>
    <li>
        <ul>
            <li>Cat 2</li>
            <li>Cat 3</li>
            <li>
                <ul>
                    <li>Cat 4</li>
                </ul>
            </li>
            <li>Cat 5</li>
            <li>
                <ul>
                    <li>Cat 6</li>
                    <li>
                        <ul>
                            <li>Cat 7</li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>Cat 8</li>
        </ul>
    </li>
</ul>


Nitpickers corner: Questioner explicitly asked for <ul>, but ordered unordered lists!? Come on...
;-)

这篇关于获取修改的预定义树遍历模型(嵌套集)到&lt; ul&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆