This is a demonstration of how to meaningfully make sense of a theoretically infinitely recursing tree stored in a database as a set of records which all specify who their parent is (the simplest way to store such a structure in a flat form, such as a database table). - Top-level entries have parent = 0; - Depth is capped at 64 levels, to simplify loop detection. - Nodes are divided into two groups: a) "folders" -- contain 0 or more nodes of any type, in any combination b) "leaves" -- may not contain other nodes, but have a URL attached. - Currently, if a node has a URL, it is assumed to be a leaf, and thus have no children, as this does not make sense for the intended implementation. - The source code is available below, if desired. [neofw_db_mysql] Warning: Could not USE database test [neofw_db_mysql] Warning: Problem running query: "SELECT id,name,url,parent FROM tree_urls": No database selected Error fetching from database: No database selected Resulting tree: --- Source: $row) { // If this is a child... if(isset($row['parent'])) { // ...tell its parent about it... $arr[$row['parent']]['childnodes'][] = $id; // ...and remove the (now useless) parent info. unset($arr[$id]['parent']); } } return $arr; } function recursive_select_nodes($arr,$nodes,$internal_depth = 0) { $selected = array(); // Error checking, or "Put that thing away, you don't know where it's been!" if($internal_depth > 64) { echo "Error: recursing deeper than 64 levels indicates probable loop formed.\n"; return $selected; } // Walk through the array of nodes we were told to select... foreach($nodes as $id) { // ...and if the node exists (I said we would need to refer quickly to a //node by its id, didn't I?)... if(isset($arr[$id])) { // ...then check if it's a parent,... if(isset($arr[$id]['childnodes'])) { // ...select its children via recursion... $arr[$id]['children'] = recursive_select_nodes($arr, $arr[$id]['childnodes'],$internal_depth + 1); // ...and erase the now useless list of child nodes. unset($arr[$id]['childnodes']); } // Finally, add it to our selected list... $selected[] = $arr[$id]; } } // ...and return the selected nodes. return $selected; } function produce($in_arr,$level = 0) { if($level > 64) { echo "Error: recursing deeper than 64 levels indicates probable loop formed.\n"; echo "WARNING: This should've been caught earlier!\n"; // Remember, recursive_select_nodes() has at least one level more than //we do: the root node. return ''; } $out = ''; foreach($in_arr as $elem) { // Print the element's name to the right depth if($level >= 0) $out .= str_repeat("\t",$level).$elem['name']; // Leaves are assumed to have no children... if(!empty($elem['url'])) { // ...so we just print them out as is. $out .= '|'.$elem['url']."\n"; } // Folders have no URLs... else { // ...so we can print the newline immediately... $out .= "\n"; // ...And recurse deeper if needed. if(!empty($elem['children'])) $out .= produce($elem['children'],$level + 1); } } return $out; } ?>