我有一些分层数据需要在一系列嵌套的UL中显示。对于每个项目,我有一个名称,一个ID和一个深度值。通常我会按深度对这些项进行分组,但实际上我需要使用我的数据创建树结构,如下所示:
这是我的问题:是否有一种很好的方法来生成有效的标记(如果我能用正确的标签打印出来,我会很喜欢它,但这很难)我的数据将被嵌套在UL中?我已经有一个有点工作的解决方案,但我得到一个单一的迷路标签。这是我的代码:
<?php
include("includes/classes/Database.class.php");
$db = new Database();
$query = "SELECT COUNT(parent.Name) - 2 as level, node.Name AS Name, node.ID
FROM Region AS node, Region AS parent
WHERE node.LeftVal BETWEEN parent.LeftVal AND parent.RightVal and node.Name <> 'Earth'
GROUP BY node.ID
ORDER BY node.LeftVal";
$results = $db->executeQuery($query);
?>
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<?php
$last_level = 0;
?>
<ul id="regionTree">
<?php
while ($row = mysql_fetch_assoc($results)) {
$link = '<li>'.PHP_EOL.'<a href="addChild.php?parentid='.$row["ID"].'">'.$row["Name"]."</a>".PHP_EOL;
$diff = $last_level - $row["level"];
if($diff == 0){
// Sibling
echo ($row["level"] != 0) ? '</li>'.PHP_EOL.$link:$link;
}
elseif($diff < 0){
// Child
$demoter = '<ul>'.PHP_EOL;
for ($i=0; $i > $diff; $i--) {
echo $demoter;
}
echo $link;
}
else{
// Parent
$promoter = '</li>'.PHP_EOL.'</ul>';
for ($i=0; $i < $diff; $i++) {
echo ($row["level"] != 0) ? $promoter.PHP_EOL."</li>":$promoter;
}
echo $link;
}
$last_level = $row["level"];
}
?>
</li>
</ul>
</body>
</html>
任何想法?
::编辑:: 我用生成的源创建了一个不验证的pastebin。 Pastebin.com
::编辑2 :: 这是Region表的模式。它是使用嵌套集模型和邻接表模型的混合设计的。
CREATE TABLE Region (
ID INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Stores the ID for the Region.',
Name VARCHAR(45) NOT NULL COMMENT 'Stores the name of the Region',
Region_Type VARCHAR(45) NOT NULL COMMENT 'Stores the Region type.',
Parent INT COMMENT 'Stores the ID of the Parent Region',
LeftVal INT NOT NULL,
RightVal INT NOT NULL,
PRIMARY KEY (ID)
) COMMENT 'Stores information about all Regions.' ENGINE=INNODB
ROW_FORMAT=DEFAULT CHARACTER SET utf8 collate utf8_general_ci;
答案 0 :(得分:8)
这应该有效:
$query = "SELECT node.Name, (COUNT( parent.Name ) -1) AS depth FROM region AS node
CROSS JOIN region AS parent
WHERE node.LeftVal BETWEEN parent.LeftVal
AND parent.RightVal
GROUP BY node.Name
ORDER BY node.LeftVal";
$result = mysql_query($query);
// Build array
$tree = array();
while ($row = mysql_fetch_assoc($result)) {
$tree[] = $row;
}
// Bootstrap loop
$result = '';
$currDepth = 0;
$lastNodeIndex = count($tree) - 1;
// Start the loop
foreach ($tree as $index => $currNode) {
// Level down? (or the first)
if ($currNode['depth'] > $currDepth || $index == 0) {
$result .= '<ul>';
}
// Level up?
if ($currNode['depth'] < $currDepth) {
$result .= str_repeat('</ul></li>', $currDepth - $currNode['depth']);
}
// Always open a node
$t = ($index == 0) ? 1 : 2;
$result .= '<li>' . $currNode['Name'];
// Check if there's chidren
if ($index != $lastNodeIndex && $tree[$index + 1]['depth'] <= $tree[$index]['depth']) {
$result .= '</li>'; // If not, close the <li>
}
// Adjust current depth
$currDepth = $currNode['depth'];
// Are we finished?
if ($index == $lastNodeIndex) {
$result .= '</ul>' . str_repeat('</li></ul>', $currDepth);
}
}
// Indent the code
// For UTF8: tidy_parse_string($result, array('indent' => true, 'show-body-only' => true), 'UTF8')
$result = tidy_parse_string($result, array('indent' => true, 'show-body-only' => true));
print $result;
Getting a modified preorder tree traversal model (nested set) into a <ul>
How to generate a tree view from this result set based on Tree Traversal Algorithm?
答案 1 :(得分:0)
前段时间我遇到了类似的问题 - 输出正确HTML树的模板 不幸的是,当时我手边只有一个模板,而不是准备带数据的数组的代码:
<? foreach ($TREE as $row): ?>
<? if($row['li']=="open"): ?>
<ul>
<? endif ?>
<? if($row['li'] == "close"): ?>
</ul>
<? endif ?>
<? if($row['id']): ?>
<? if($id == $row['id']): ?>
<li><?=$row['title']?></li>
<? else: ?>
<li><a href="?id=<?=$row['id']?>"><?=$row['title']?></a></li>
<? endif ?>
<? endif ?>
<? endforeach ?>
我会尝试找到代码并在此处发布。虽然它不是太复杂。主要思想是将递归树“展开”到普通列表(添加了一些“服务”行,不包含要显示的数据,只包含标记标记)。
我不会称之为太好的解决方案,但这是我能够尽可能地将业务逻辑与显示逻辑分开的最佳结果。
代码可以简化,因为它支持链接突出显示(它旨在输出网站结构)。
答案 2 :(得分:-1)
我会创建一个很好的列表。然后用CSS格式列表,参见示例。破折号可以用背景图像完成。我用过level2.png(包含一个破折号)和level3.png(包含2个破折号)。
奇数偶数不能100%正确,但列表的格式似乎是正确的。您可以考虑在场外添加更多关卡,它的工作方式相同。
这样你就有了正确的html,显示了使它成为语义的数据之间的关系。另一方面,您可以灵活地按照自己的方式显示它,并且无需额外格式化即可添加更多数据。
<html>
<head>
<style type="text/css">
* {
font-size: 11px;
font-family: tahoma;
background-repeat: no-repeat;
}
.odd {
background-color: #ccc;
}
.even {
}
ul, li {
width: 300px;
padding: 0px;
padding: 0px;
}
ul.level1 li span {
}
ul.level2 li span {
padding-left: 50px;
background-image: url(level2.png);
}
ul.level3 li span {
padding-left: 100px;
background-image: url(level3.png);
}
</style>
</head>
<body>
<?PHP
$i=0;
echo '<ul class="level1">';
for($x=0; $x<10; $x++) {
echo '<li class="'.(($i%2) ? 'odd' : 'even').'"><span>level1-'.$i.'</span>';
$i++;
echo '<ul class="level2">';
for($y=0; $y<10; $y++) {
$i++;
echo '<li class="'.(($i%2) ? 'odd' : 'even').'"><span>level2-'.$y.'</span>';
echo '<ul class="level3">';
for($z=0; $z<10; $z++) {
$i++;
echo '<li class="'.(($i%2) ? 'odd' : 'even').'"><span>level3-'.$z.'</span>';
echo '</li>';
}
echo '</ul>';
echo '</li>';
}
echo '</ul>';
echo'</li>';
}
echo '</ul>';
?>
</body>