Creating nested ULs based on depth data

I have some hierarchical data that I need to display in a series of nested ULs. For each element, I have a name, identifier, and depth value. Usually I just grouped these elements by depth, but I really need to create a tree structure with my data, for example: My sample data in MySQL Workbench

Here's my question: is there a good way to generate valid markup (I would love it if I could print it using the correct tab, but it will be difficult), where will my data be wrapped in nested UL? I already have a solution that works, but I get the only trick. Here is the code I have for this:

<?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> 

Any ideas?

:: Edit :: I created a pastebin with a created source that is not checked. Pastebin.com

:: EDIT 2 :: Here is the schema for the Region table. It is designed using a hybrid model of nested sets and an adjacency list model.

 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; 
+4
source share
3 answers

This should work:

 $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 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 the modified pre-order tree traversal model (nested set) in <ul>

How to create a tree view from this result set based on a tree traversal algorithm?

How to create an array from this result set (nested categories stored in a database with a workaround)?

+8
source

Some time ago, I came across a similar problem - a template for outputting the correct HTML tree.
Unfortunately, at that time I only had the template at hand, and not the code that prepared the data array:

 <? 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 ?> 

I will try to find the code and post it here. Although it is not too difficult. The main idea is to "expand" the recursive tree into a regular list (when adding some added "service" lines, data is not displayed, but only tag tags).

I would not call it too pleasant a solution, but it was the best result, I was able to try as much as possible to separate the business logic from the display logic.

The code can be simplified, although at the moment it supports the allocation of links (it is intended to display the structure of the site).

0
source

I would just create a good list. Then, using the CSS format, see Example. Dashes can be made with a background image. I used level2.png (contains one dash) and level3.png (contains 2 dashes).

level2.png

level3.png

Odd-even does not work 100% correctly, but formatting your list seems to be correct. You might consider adding more levels, this works the same way.

So you have the correct html showing the relationship between the data that makes it semantic. On the other hand, you have the flexibility to show it the way you want, and allows you to add additional data without additional formatting.

 <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> 

-one
source

Source: https://habr.com/ru/post/1396490/


All Articles