How do you convert a parent-child (adjacency) table to a nested set using PHP and MySQL?

后端 未结 2 1756
我在风中等你
我在风中等你 2020-12-07 19:25

I\'ve spent the last few hours trying to find the solution to this question online. I\'ve found plenty of examples on how to convert from nested set to adjacency... but few

2条回答
  •  执笔经年
    2020-12-07 20:09

    I found an answer online and updated the question on this page to show others how it is done.

    UPDATE - PROBLEM SOLVED

    First off, I had mistakenly believed that the source table (the one in adjacent-lists format) needed to be altered to include a source node. This is not the case. Secondly, I found a class via BING that does the trick. I've altered it for PHP5 and converted the original author's mysql related bits to basic PHP. He was using some DB class. You can convert them to your own database abstraction class later if you want.

    Obviously, if your "source table" has other columns that you want to move to the nested set table, you will have to adjust the write method in the class below.

    Hopefully this will save someone else from the same problems in the future.

    i_count = 1;
                $this->a_link= $a_link;
            }
    
            public function traverse($i_id) 
            {
                $i_lft = $this->i_count;
                $this->i_count++;
    
                $a_kid = $this->get_children($i_id);
                if ($a_kid) 
                {
                    foreach($a_kid as $a_child) 
                    {
                        $this->traverse($a_child);
                    }
                }
                $i_rgt=$this->i_count;
                $this->i_count++;
                $this->write($i_lft,$i_rgt,$i_id);
            }   
    
            private function get_children($i_id) 
            {
                return $this->a_link[$i_id];
            }
    
            private function write($i_lft,$i_rgt,$i_id) 
            {
    
                // fetch the source column
                $s_query = "SELECT * FROM `adjacent_table` WHERE `id`  = '".$i_id."'";
                if (!$i_result = mysql_query($s_query))
                {
                    echo "
    $s_query
    \n"; throw new Exception(mysql_error()); } $a_source = array(); if (mysql_num_rows($i_result)) { $a_source = mysql_fetch_assoc($i_result); } // root node? label it unless already labeled in source table if (1 == $i_lft && empty($a_source['category'])) { $a_source['category'] = 'ROOT'; } // insert into the new nested tree table // use mysql_real_escape_string because one value "CD's" has a single ' $s_query = " INSERT INTO `nested_table` (`id`,`lft`,`rgt`,`category`) VALUES ( '".$i_id."', '".$i_lft."', '".$i_rgt."', '".mysql_real_escape_string($a_source['category'])."' ) "; if (!$i_result = mysql_query($s_query)) { echo "
    $s_query
    \n"; throw new Exception(mysql_error()); } else { // success: provide feedback echo "

    $s_query

    \n"; } } } mysql_connect('localhost','USER','PASSWORD') or die(mysql_error()); mysql_select_db('DATABASE') or die(mysql_error()); // build a complete copy of the adjacency table in ram $s_query = "SELECT `id`,`father_id` FROM `adjacent_table`"; $i_result = mysql_query($s_query); $a_rows = array(); while ($a_rows[] = mysql_fetch_assoc($i_result)); $a_link = array(); foreach($a_rows as $a_row) { $i_father_id = $a_row['father_id']; $i_child_id = $a_row['id']; if (!array_key_exists($i_father_id,$a_link)) { $a_link[$i_father_id]=array(); } $a_link[$i_father_id][]=$i_child_id; } $o_tree_transformer = new tree_transformer($a_link); $o_tree_transformer->traverse(0); ?>

    Here is the output:

    INSERT INTO nested_table (id,lft,rgt,category) VALUES ( '4', '3', '4', 'Hard Cover' )

    INSERT INTO nested_table (id,lft,rgt,category) VALUES ( '5', '5', '6', 'Large Format' )

    INSERT INTO nested_table (id,lft,rgt,category) VALUES ( '1', '2', '7', 'Books' )

    INSERT INTO nested_table (id,lft,rgt,category) VALUES ( '2', '8', '9', 'CD\'s' )

    INSERT INTO nested_table (id,lft,rgt,category) VALUES ( '6', '11', '12', 'Vintage' )

    INSERT INTO nested_table (id,lft,rgt,category) VALUES ( '3', '10', '13', 'Magazines' )

    INSERT INTO nested_table (id,lft,rgt,category) VALUES ( '0', '1', '14', 'ROOT' )

提交回复
热议问题