PHP Traversing mySQL Node tree

I'm having trouble trying to move nodes or parent nodes up or down ... not that good at math.

CREATE TABLE IF NOT EXISTS `pages` (   `page-id` mediumint(8) unsigned

      

NOT NULL AUTO_INCREMENT, page-left

mediumint (8) unsigned NOT NULL,
page-right

smallint (8) unsigned NOT NULL, page-title

text NOT NULL,
page-content

text NOT NULL,
page-time

int (11) unsigned NOT NULL, page-slug

text NOT NULL,
page-template

text NOT NULL,
page-parent

mediumint (8) unsigned NOT NULL, page-type

text NOT NULL, PRIMARY KEY ( page-id

)) ENGINE = MyISAM DEFAULT CHARSET = latin1;

INSERT INTO pages

( page-id

, page-left

, page-right

, page-title

, page-content

, page-time

, page-slug

, page-template

, page-parent

, page-type

) VALUES (17, 1, 6, '1', '0,' PARENT ',' ', 0' '), (18, 2, 5, '2', '', 0, 'SUB', '', 17, ''), (19, 3, 4, 3 ',' ', 0,' SUB-SUB ',' ', 18,' ' ), (20, 7, 8, '5', '', 0, 'TEST', '', 0, '');

As an example, how would I move TEST above PARENT and say move SUB below SUB-SUB, playing with the page IDs / left / right? No code required, just help with SQL concept or math for it, help me figure out how best to move it ...

0


a source to share


1 answer


So basically you want to convert an adjacency list to a nested set? First update the adjacency list (i.e. update the page_parent values ​​to the correct values ​​for your new tree) and then do the transform below.

Using PHP (base code, untested):

class Tree
{    
    private $count = 0;
    private $data = array();

    /**
     * Rebuild nested set
     * 
     * @param $rawData array Raw tree data
     */
    public function rebuild($rawData)
    {
        $this->data = $rawData;
        $this->count = 1;
        $this->traverse(0);        
    }

    private function traverse($id)
    {
        $lft = $this->count;
        $this->count++;

        if (isset($this->data[$id])) {
            $kid = $this->data[$id];
            if ($kid) {
                foreach ($kid as $c) {
                    $this->traverse($c);
                }
            }
        }

        $rgt = $this->count;
        $this->count++;

        // TODO: Update left and right values to $lft & $rgt in your DB for page_id $id
        ...
    }
}

      

When you call this, $ rawData should contain an array of IDs indexed by the parent ID, you can create it (based on the table structure) like this ($ db should contain an active PDO connection object):



    $sql = 'SELECT page_id, page_parent FROM pages ORDER BY page_parent';

    $stmt = $db->prepare($sql);
    $rawData = array();
    $stmt->execute();
    while ($row = $stmt->fetch()) {
        $parent = $row['page_parent'];
        $child = $row['page_id'];
        if (!array_key_exists($parent, $rawData)) {
            $rawData[$parent] = array();
        }
        $rawData[$parent][] = $child;
    }

      

To convert, you need something like:

$tree = new Tree();
$tree->rebuild($rawData);

      

So basically you are creating an array containing all the nodes in the tree, indexed by the parent, which will be recursively traversed to determine the correct left and right values ​​on the node.

BTW You can do this in plain SQL (after you adapt the table and column names): http://bytes.com/topic/mysql/answers/638123-regenerate-nested-set-using-parent_id-structure

+3


a source







All Articles