NYCPHP Meetup

NYPHP.org

displaying a tree defined by one table

(kris)janis p gale sharpwit at hotmail.com
Thu Oct 17 06:13:52 EDT 2002


the trees thread made me realize it was a topic near and dear to my heart, since way-back-when i had devoted pretty much an entire day's research-and-development effort towards devising a method of not only creating an arbitrarily-deep tree structure using a single self-referencing table, but also be able to traverse such a structure with relative ease...

my development environment at the time was a windows nt box running coldfusion and access as a db -- so recursion was NOT an option, not only because coldfusion doesn't even support recursion, but also due to the total lack of resources on that puny development box...

call me crazy, but i actually Enjoy developing iterative algorithms for problems that usually lend themselves to recursion, especially when even brainstorming such an iterative solution would send most developers screaming out the door in search of fresh air and daylight.

anyways, porting my coldfusion script to php proved extremely rudimentary.

i created a basic table for this exercise, called "test"
it has three fields -- id [int], parent_id [int], and name [varchar(64)]
there's an index on id (primary) and parent_id

contents of "test":

id, parent_id, name

3, 0, primary1
2, 0, primary2
1, 0, primary3
5, 3, secondary1
6, 3, secondary2
4, 1, secondary3
7, 5, tertiary1
8, 4, tertiary2
9, 4, tertiary3


my assumption here is that
a top-level item's parent_id is to be zero.
(i could have just as easily used NULL.)


the code to display this tree:
----


<?php

$mc = mysql_connect("localhost") or die("!mysql_connect");
$md = mysql_select_db("mysql",$mc) or die("!mysql_select_db");

$mq = mysql_query("SELECT id, parent_id, name FROM test ORDER BY name") or die("!mysql_query");
$nrows = mysql_num_rows($mq);

$data = array_fill(0,$nrows,NULL);
$n = 0;
while($mfa = mysql_fetch_array($mq,MYSQL_ASSOC))
 $data[$n++] = $mfa;

mysql_free_result($mq);
mysql_close($mc);

$id_list = array();
$row_list = array();
$depth_list = array();

for($n = 0 ; $n < $nrows ; $n++)
 if($data[$n]["parent_id"] == 0)
 { array_push($id_list,$data[$n]["id"]);
  array_push($row_list,$n);
  array_push($depth_list,0);
 }

while(count($id_list) < $nrows)
{ $id_temp = array();
 $row_temp = array();
 $depth_temp = array();
 for($i = 0 ; $i < count($id_list) ; $i++)
 { $id = $id_list[$i];
  $row = $row_list[$i];
  $depth = $depth_list[$i];
  array_push($id_temp,$id);
  array_push($row_temp,$row);
  array_push($depth_temp,$depth);
  for($j = 0 ; $j < $nrows ; $j++)
   if(($data[$j]["parent_id"] == $id)
   && (array_search($data[$j]["id"],$id_list) == NULL))
   { array_push($id_temp,$data[$j]["id"]);
    array_push($row_temp,$j);
    array_push($depth_temp,$depth + 1);
   }
 }
 $id_list = $id_temp;
 $row_list = $row_temp;
 $depth_list = $depth_temp;
}

print('<pre>');
for($n = 0 ; $n < $nrows ; $n++)
 print(str_repeat("----",$depth_list[$n]) . $data[$row_list[$n]]["name"] . '<br>');
print('</pre>');

?>


----
the useful variables created by the end result of this code
is three arrays...

$nrows
number of rows in your dataset

$data[][]
contains the entirety of your data, in a two-dimensional array

$row_list[]
a single dimentional array that you'll use to index rows
of $data in tree-order, not in alphabetical or row-order
(see the very end of the above code to see what i mean)

$depth_list[]
the depth of each item in the tree, in tree-order
(see above how i used this variable to indent
the displayed item to show its depth in the tree)

----

see the code in action:
http://krisgale.com/code/tree.php

----

incidentally, anyone have a job for me?
i truly miss solid development work like this...
(database-driven web applications is my forté)

my resumé:
http://krisgale.com/work/kpg_resume.gif


regards,
- kris gale

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.nyphp.org/pipermail/talk/attachments/20021017/86eb2c2b/attachment.html>


More information about the talk mailing list