Binary Tree Using PHP & MySQL

Reply

Join Date: Aug 2007
Posts: 88
Reputation: hemgoyal_1990 is an unknown quantity at this point 
Solved Threads: 7
hemgoyal_1990's Avatar
hemgoyal_1990 hemgoyal_1990 is offline Offline
Junior Poster in Training
 
0
  #11
27 Days Ago
Originally Posted by wenzlerpaul View Post
Hi,

You can try to approach this in different ways, however, you will need to see how you would layout your page too. Based on my experience, the layout you were looking at will grow wider so you will need to limit how much you can show per page.

I will try to give you 2 approaches I can think of that might work for you.

First, limit your display up to 15 IDs only, this will allow you to put as much details as you need per ID, please refer to the illustration taken from my genealogy system:

http://i34.tinypic.com/j9x63b.jpg

This method will allow your database to breathe from over-processing because of recursive calls.
What I did with this was just layout an html page and used a function call to get left and right till you fill all 15 slots. Here is the php code I use:

  1. function GetDownline($member_id,$direction)
  2. {
  3. $getdownlinesql = @mysql_fetch_assoc(@mysql_query('select memberid,placementid,position from `yourrelationaltable` where placementid="'.$member_id.'" and position="'.$direction.'"'));
  4. $getdownline = $getdownlinesql['memberid'];
  5. return $getdownline;
  6. }
  7.  
  8. then simply call it with:
  9. $firstleft = GetDownline('headmemberidhere','Left'); //for first left
  10. $firstright = GetDownline('headmemberidhere','Right'); //for first right
  11. echo $firstleft;
  12. echo $firstright;
Now for the next left or right

  1. $secondleftofleft = GetDownline($firstleft,'Left'); //for second left of first left
  2. $secondrightofleft = GetDownline($firstleft,'Right'); //for second right of first left
  3.  
  4. echo $secondleftofleft;
  5. echo $secondrightofleft;
  6.  
  7. $secondleftofright = GetDownline($firstright,'Left'); for second left of first right
  8. $secondrightofright = GetDownline($firstright,'Right'); for second right of first right
  9.  
  10. echo $secondleftofright;
  11. echo $secondrightofright;

..And so on, now you can build your 15 tree line on a page, to give the effect of going downline, you can make all of the buttons clickable carrying their own member id's so it makes it the top of the tree, just to a GET or POST method to assign a new value for headmemberidhere that serves as your head of the tree.

Note:
This is not my exact code and is for illustration purposed only, but the code will work as is.

That is the simplest method to have a nice layout of the binary tree.

The next one is the full recursive method similar to Atli's post.

However, this approach is not recommended if you are on a shared server or have a large database like I have.

The full recursive method I did was a bit complicated to get the effect due to the nature of my database structure. I actually had an existing database to work on so I had difficulties adapting or creating the proper code since I had to adapt to the database instead of me creating the perfect code that will do a simple recursive structure.

Below is the method I used to make recursion work from top to bottom of the tree in full view.

I did three function calls to so that each set will call different codes at the same time in recursion, I am not sure how to do this easily too because of the existing database structure.

Here is an illustrative php code for you:

  1. <?php
  2. include("../includes/config.php");
  3. //my database connection is set in my config, otherwise, just create your own db connect
  4. $defaultmcode = 'yourdefaultidhere';
  5. if($_GET['topmcode']){
  6. $topmcode = trim($_GET['topmcode']);
  7. }else{
  8. $topmcode = $defaultmcode;
  9. }
  10. $topmcode = ltrim($topmcode);
  11. $topmcode = rtrim($topmcode);
  12. $topmcode = strtoupper($topmcode);
  13. //my memberid are alphanumerics and all caps so I had to conver all to upper case, else, comment the above strtoupper call
  14.  
  15. //get Downline of a Member, this function is needed so that you can simply call left or right of the memberid you are looking for
  16. function GetDownline($member_id,$direction)
  17. {
  18. $getdownlinesql = @mysql_fetch_assoc(@mysql_query('select memid,placementid,position from `yourtablehere` where placementid="'.$member_id.'" and position="'.$direction.'"'));
  19. $getdownline = $getdownlinesql['memid'];
  20. return $getdownline;
  21. }
  22.  
  23. //get the child of the member, this section will look for left or right of a member, once found, it will call GetNextDownlines() function to assign new memberid variables for left or right
  24. function GetChildDownline($member_id)
  25. {
  26. $getchilddownlinesql = @mysql_query('select memid,placementid,position from `yourtablehere` where placementid="'.$member_id.'" ORDER BY position');
  27. while($childdownline = mysql_fetch_array($getchilddownlinesql)){
  28. $childdownlinecode = $childdownline['memid'];
  29. $direction = $childdownline['position'];
  30. if($direction=='L'){
  31. if($childdownlinecode){
  32. //this is where you play with your html layout
  33. echo $childdownlinecode.'<br>';
  34. GetNextDownlines($childdownlinecode,'L');
  35. }
  36. }
  37.  
  38. if($direction=='R'){
  39. if($childdownlinecode){
  40. //this is where you play with your html layout
  41. echo $childdownlinecode.'<br>';
  42. GetNextDownlines($childdownlinecode,'R');
  43. }
  44. }
  45. }
  46. }
  47.  
  48. //recursive function to call the functions and start all over again, this is where you can get the newly assigned memberid, call the GetChildDownline() that gets the left or right, then recycle all codes
  49. function GetNextDownlines($member_id,$direction)
  50. {
  51. if($direction=='L'){
  52. $topleft = GetDownline($member_id,'L');
  53. if($topleft){
  54. //this is where you play with your html layout
  55. echo $topleft.'<br>';
  56. }
  57. $getleftdownlinesql = @mysql_query('select memid,placementid,position from `yourtablehere` where placementid="'.$topleft.'" ORDER BY position');
  58. while($getleftdownline = mysql_fetch_array($getleftdownlinesql)){
  59. $leftdownline = $getleftdownline['memid'];
  60. $leftdirection = $getleftdownline['position'];
  61.  
  62. if($leftdirection=='L'){
  63. if($leftdownline){
  64. //this is where you play with your html layout
  65. echo $leftdownline.'<br>';
  66. GetChildDownline($leftdownline);
  67. }
  68. }
  69.  
  70. if($leftdirection=='R'){
  71. if($leftdownline){
  72. //this is where you play with your html layout
  73. echo $leftdownline.'<br>';
  74. GetChildDownline($leftdownline);
  75. }
  76. }
  77. }
  78. }
  79.  
  80.  
  81. if($direction=='R'){
  82. $topright = GetDownline($member_id,'R');
  83. if($topright){
  84. echo $topright.'<br>';
  85. }
  86. $getrightdownlinesql = @mysql_query('select memid,placementid,position from `yourtablehere` where placementid="'.$topright.'" ORDER BY position');
  87. while($getrightdownline = @mysql_fetch_array($getrightdownlinesql)){
  88. $rightdownline = $getrightdownline['memid'];
  89. $rightdirection = $getrightdownline['position'];
  90.  
  91. if($rightdirection=='L'){
  92. if($rightdownline){
  93. //this is where you play with your html layout
  94. echo $rightdownline.'<br>';
  95. GetChildDownline($rightdownline);
  96. }
  97. }
  98.  
  99. if($rightdirection=='R'){
  100. if($rightdownline){
  101. //this is where you play with your html layout
  102. echo $rightdownline.'<br>';
  103. GetChildDownline($rightdownline);
  104. }
  105. }
  106.  
  107. }
  108. }
  109. }
  110.  
  111. ?>
  112. <html>
  113. <head>
  114. <title>Genealogy</title>
  115. <meta http-equiv=Content-Type content="text/html; charset=utf-8">
  116. <meta http-equiv=content-language content=en>
  117. <link href="styles.css" type=text/css rel=stylesheet>
  118. </head>
  119. <body>
  120. <table cellpadding="0" cellspacing="0" width="100%" border="0" class="noborder">
  121. <tr>
  122. <td>
  123. <?php
  124. echo $topmcode.'<br>';
  125. GetNextDownlines($topmcode,'L');
  126. GetNextDownlines($topmcode,'R');
  127. ?>
  128.  
  129. </td>
  130. </tr>
  131. </table>
  132. </body>
  133. </html>

This is not the full code, but it gives you insights on how to do full recursive view on your data structure. Also, this is a product of 3:30 AM with no sleep yet so it maybe sloppy and redundant... hehe

If you can make it thinner or smaller it would be better, or if there is a real way to recycles codes without my redundancies....

I hope this helps

Thank You For Your Help..
Your Code is Work Fine and Very Helpful for Me.
but I Have Some Trouble in The Above Code. I Have Created a Page Called http://www.liferider.info/mlm/tree.php This Page Create Tree View from Your Above Given Code.
This Code Have a Bug That This Print all Node in Every Section of Binary Tree.
Please Check the above Page for Illustration.

Please Tell me How I Can Print only Child Node in Binary Tree. my Database Schema is Given Below:

  1. | memid | | placementid | | position |
  2. | 1 | | 0 | | 0 |
  3. | 2 | | 1 | | L |
  4. | 3 | | 1 | | R |
  5. | 4 | | 2 | | L |
  6. | 5 | | 2 | | R |
  7. | 6 | | 3 | | L |
  8. | 7 | | 3 | | R |
  9. | 8 | | 4 | | L |
  10. | 9 | | 4 | | R |
  11. | 10 | | 5 | | L |
  12. | 11 | | 5 | | R |
  13. | 12 | | 6 | | L |
  14. | 13 | | 6 | | R |
  15. | 14 | | 7 | | L |
  16. | 15 | | 7 | | R |
Last edited by hemgoyal_1990; 27 Days Ago at 5:29 am.
http://www.kuchamancity.com
Hem Web Solution..
Behind Every Successful Man, There is an Untold Pain in His Heart.
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 88
Reputation: hemgoyal_1990 is an unknown quantity at this point 
Solved Threads: 7
hemgoyal_1990's Avatar
hemgoyal_1990 hemgoyal_1990 is offline Offline
Junior Poster in Training
 
0
  #12
25 Days Ago
Please Help..
I am Very Much Need Help...
http://www.kuchamancity.com
Hem Web Solution..
Behind Every Successful Man, There is an Untold Pain in His Heart.
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 88
Reputation: hemgoyal_1990 is an unknown quantity at this point 
Solved Threads: 7
hemgoyal_1990's Avatar
hemgoyal_1990 hemgoyal_1990 is offline Offline
Junior Poster in Training
 
0
  #13
23 Days Ago
Originally Posted by Atli View Post
Hey.
Sorry it took me so long to respond. Been busy.

Anyhow, here is my take on this problem.

Positioning the IDs themselves can be done fairly easily with HTML, but the lines between parent-child IDs aren't as easily created.

I created this, which creates a HTML hierarchy of <div> elements, which positions the IDs with their parents. I over-commented the code, so I won't explain to much.
  1. <?php
  2. /**
  3.  * Handles creating and/or printing a Tree-Like HTML output, complete with
  4.  * all necessary CSS styles.
  5.  *
  6.  * Assumes a MySQL database table structure like so:
  7.  * CREATE TABLE `name` (
  8.  * `id` int(11) NOT NULL AUTO_INCREMENT,
  9.  * `parentID` int(11) DEFAULT NULL,
  10.  * PRIMARY KEY (`id`)
  11.  * );
  12.  *
  13.  * Public methods:
  14.  * createTree - Returns the HTML tree-view.
  15.  * printTree - Prints the HTML tree-view.
  16.  *
  17.  * Private methods
  18.  * fetchTree - Reads the complete tree structure into an array.
  19.  * buildHtml - Builds the HTML div hierarchy based.
  20.  */
  21. class TreeView
  22. {
  23. private $bgColor = "rgba(0, 100, 0, 0.10)";
  24.  
  25. private $dbLink;
  26. private $tblName;
  27.  
  28. /**
  29.   * Default constructor
  30.   * @param mysqli $dbLink A open MySQL (mysqli) connection.
  31.   * @throws Exception
  32.   */
  33. public function __construct(mysqli $dbLink)
  34. {
  35. if($dbLink != null && $dbLink->connect_errno == 0)
  36. {
  37. $this->dbLink = $dbLink;
  38.  
  39. // This number is added the the container DIV ID, so that we can
  40. // tell the DIVs a part if there are more than one view created.
  41. if(!isset($GLOBALS['TreeView_DivID'])) {
  42. $GLOBALS['TreeView_DivID'] = 0;
  43. }
  44. }
  45. else
  46. {
  47. throw new Exception("The mysqli object provided is invalid.");
  48. }
  49. }
  50.  
  51. /**
  52.   * Creates a descending tree-like view of the tree-structure in the given
  53.   * database table and returns it as a string.
  54.   * @param <type> $tblName The name of the database table to use.
  55.   * @return <string> The string output.
  56.   * @throws Exception
  57.   */
  58. public function createTree($tblName)
  59. {
  60. if(!isset($dbName, $tblName) || (empty($dbName) && empty($tblName)))
  61. {
  62. throw new Exception("Failed to create the tree. Table or database information is invalid");
  63. }
  64. else
  65. {
  66. // Set up variables
  67. $this->tblName = $tblName;
  68. $treeData = array();
  69. $output = "";
  70.  
  71. // Create the output
  72. $this->fetchTree($treeData);
  73.  
  74. // Set up the CSS styles, and create the container DIV.
  75. $divID = "TreeView_ContainerDiv_" . $GLOBALS['TreeView_DivID'];
  76. $output = <<<HTML
  77. <style type="text/css">
  78. div#{$divID} { margin: 0; padding: 0; text-align: center; }
  79. div#{$divID} div { margin: 0; padding: 0 10px; float: left; background-color: {$this->bgColor}; }
  80. div#{$divID} p { margin: 0; padding: 0; }
  81. </style>
  82. <div id="{$divID}">
  83. HTML;
  84.  
  85. // Add the DIV hierachy.
  86. $this->buildHtml($treeData, $output);
  87.  
  88. // Increment the DIV ID number
  89. $GLOBALS['TreeView_DivID']++;
  90.  
  91. return $output;
  92. }
  93. }
  94.  
  95. /**
  96.   * Prints a descending tree-like view of the tree-structure in the given
  97.   * database table.
  98.   * @param <type> $tblName The name of the database table to use.
  99.   * @throws Exception
  100.   */
  101. public function printTree($tblName)
  102. {
  103. echo $this->createTree($tblName);
  104. }
  105.  
  106. /**
  107.   * A recursive function that fetches a tree-structure from a database into an array.
  108.   * @global <mysqli> $dbLink A open MySQLI connection.
  109.   * @param <number> $parentID The ID the current recursion uses as a root.
  110.   */
  111. private function fetchTree(&$parentArray, $parentID=null)
  112. {
  113. global $dbLink;
  114.  
  115. // Create the query
  116. if($parentID == null) {
  117. $parentID = -1;
  118. }
  119. $sql = "SELECT `id` FROM `{$this->tblName}` WHERE `parentID`= ". intval($parentID);
  120.  
  121. // Execute the query and go through the results.
  122. $result = $dbLink->query($sql);
  123. if($result)
  124. {
  125. while($row = $result->fetch_assoc())
  126. {
  127. // Create a child array for the current ID
  128. $currentID = $row['id'];
  129. $parentArray[$currentID] = array();
  130.  
  131. // Print all children of the current ID
  132. $this->fetchTree($parentArray[$currentID], $currentID);
  133. }
  134. $result->close();
  135. }
  136. else {
  137. die("Failed to execute query! ($level / $parentID)");
  138. }
  139. }
  140.  
  141. /**
  142.   * Builds a HTML <div> hierarchy from the tree-view data.
  143.   * Each parent is encased in a <div> with all their child nodes, and each
  144.   * of the children are also encased in a <div> with their children.
  145.   * @param <array> $data The tree-view data from the fetchTree method.
  146.   * @param <string> $output The <div> hierachy.
  147.   */
  148. private function buildHtml($data, &$output)
  149. {
  150. // Add the DIV hierarchy.
  151. foreach($data as $_id => $_children)
  152. {
  153. $output .= "<div><p>{$_id}</p>";
  154. $this->buildHtml($_children, $output);
  155. $output .= "</div>";
  156. }
  157. }
  158. }
  159. ?>

Which you could use like so:
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Tree-view Test</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf8">
  6. </head>
  7. <body>
  8. <?php
  9. $dbLink = new mysqli("localhost", "usr", "pwd", "dbName");
  10.  
  11. $treeView = new TreeView($dbLink);
  12. $treeView->printTree('tblName');
  13.  
  14. $dbLink->close();
  15. ?>
  16. </body>
  17. </html>
This won't draw lines between the IDs, but it will position them nicely. I though about using JavaScript to draw the lines, but I'm way to tired for that at the moment xD

P.S.
Don't try this using Internet Explorer. It has a problem rendering CSS rules defined this decade, so the background colors won't show.

Friedn Could You Tell me That Where I Put Table name in The Above Code.
I am Created a Table Called mlm_data with Below Field:
  1. ID parentID
  2. 1 0
  3. 2 1
  4. 3 1
  5. 4 2
  6. 5 2
  7. 6 3
  8. 7 3
  9. 8 4
  10. 9 4
  11. 10 5
  12. 11 5
  13. 12 6
  14. 13 6
  15. 14 7
  16. 15 7


Please Help me It's Very Urgent.
Last edited by hemgoyal_1990; 23 Days Ago at 5:01 am.
http://www.kuchamancity.com
Hem Web Solution..
Behind Every Successful Man, There is an Untold Pain in His Heart.
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 423
Reputation: Atli is on a distinguished road 
Solved Threads: 53
Atli's Avatar
Atli Atli is offline Offline
Posting Pro in Training
 
0
  #14
23 Days Ago
Originally Posted by hemgoyal_1990 View Post
Friedn Could You Tell me That Where I Put Table name in The Above Code.
In line #12 of the second code, where it says 'tblName' ;-)
Please do not ask for help in a PM. Use the forums.
And use [code] tags!
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 88
Reputation: hemgoyal_1990 is an unknown quantity at this point 
Solved Threads: 7
hemgoyal_1990's Avatar
hemgoyal_1990 hemgoyal_1990 is offline Offline
Junior Poster in Training
 
0
  #15
23 Days Ago
Originally Posted by Atli View Post
In line #12 of the second code, where it says 'tblName' ;-)

I Put the Table name where u specified and run my code but there nothing print..
in below url format:
http://yourdomain.com/mlm/tree.php

is there the above url is right or may change the url.
http://www.kuchamancity.com
Hem Web Solution..
Behind Every Successful Man, There is an Untold Pain in His Heart.
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 423
Reputation: Atli is on a distinguished road 
Solved Threads: 53
Atli's Avatar
Atli Atli is offline Offline
Posting Pro in Training
 
0
  #16
23 Days Ago
Did you include the class or just put it at the top of the page?

Ideally, you would put the class (the first code I posted in post #10) into a file, lets call it "class.TreeView.php".

Then you create your tree file, "tree.php", and you put this into it:
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Tree-view Test</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf8">
  6. </head>
  7. <body>
  8. <?php
  9. // Turn on error reporting, just in case.
  10. ini_set('display_errors', true);
  11. error_reporting(E_ALL);
  12.  
  13. // Fetch the TreeView class from the other file.
  14. include("class.TreeView.php");
  15.  
  16. // Open a database connection
  17. // TODO: Replace the info here with your real info.
  18. $dbLink = new mysqli("localhost", "usr", "pwd", "dbName");
  19.  
  20. // Create an instance of the TreeView class.
  21. $treeView = new TreeView($dbLink);
  22.  
  23. // Print the tree view
  24. // TODO: Insert your real table name here.
  25. $treeView->printTree('tblName');
  26.  
  27. $dbLink->close();
  28. ?>
  29. </body>
  30. </html>
In that code, you need to fill out both the MySQL database info and replace the 'tblName' with the name of your table.
Please do not ask for help in a PM. Use the forums.
And use [code] tags!
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 423
Reputation: Atli is on a distinguished road 
Solved Threads: 53
Atli's Avatar
Atli Atli is offline Offline
Posting Pro in Training
 
0
  #17
23 Days Ago
Ohh, I just realized, there is a bug in my class.

Line #60. Replace it with:
  1. if(!isset($tblName) || empty($tblName))

Minor oversight. Sorry ;-)
Last edited by Atli; 23 Days Ago at 1:44 pm.
Please do not ask for help in a PM. Use the forums.
And use [code] tags!
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 88
Reputation: hemgoyal_1990 is an unknown quantity at this point 
Solved Threads: 7
hemgoyal_1990's Avatar
hemgoyal_1990 hemgoyal_1990 is offline Offline
Junior Poster in Training
 
0
  #18
22 Days Ago
i am compile my code with your guideline and follow that there are nothing print. i think there are some mistake in my database structure.
i am using the below table structure:
  1. id parentID
  2. 1 0
  3. 2 1
  4. 3 1
  5. 4 2
  6. 5 2
  7. 6 3
  8. 7 3
  9. 8 4
  10. 9 4
  11. 10 5
  12. 11 5
  13. 12 6
  14. 13 6
  15. 14 7
  16. 15 7
http://www.kuchamancity.com
Hem Web Solution..
Behind Every Successful Man, There is an Untold Pain in His Heart.
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 423
Reputation: Atli is on a distinguished road 
Solved Threads: 53
Atli's Avatar
Atli Atli is offline Offline
Posting Pro in Training
 
0
  #19
22 Days Ago
Yea, I see.
My example uses -1 as the parentID for root-level rows. You need to either change the value in your database or alter the code to use 0 instead (you can do that on line #117 of the code).
Please do not ask for help in a PM. Use the forums.
And use [code] tags!
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 88
Reputation: hemgoyal_1990 is an unknown quantity at this point 
Solved Threads: 7
hemgoyal_1990's Avatar
hemgoyal_1990 hemgoyal_1990 is offline Offline
Junior Poster in Training
 
0
  #20
21 Days Ago
Thanx Atil for Helping me Out.

I am Very Thankful for You. You Solve my Very big Problem.
http://www.kuchamancity.com
Hem Web Solution..
Behind Every Successful Man, There is an Untold Pain in His Heart.
Reply With Quote Quick reply to this message  
Reply

Tags
mysql, php

Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC