PHP Moving mySQL Tree Node

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-25 21:25:09

问题


I am having trouble trying to move sub 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 example how would I move TEST up above PARENT and say move SUB down below SUB-SUB by playing with the page-left/page-right IDs? Code is not required just help with the SQL concept or math for it, would help me understand how to move it better...


回答1:


So basically you want to convert an adjacency list to a nested set? First update your adjacency list (ie. update the page_parent values to the correct values for your new tree), then run the conversion below.

Using PHP (basic 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 ID's, indexed by parent-id, you could create it (based on your table structure) as follows ($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 do the conversion you would need something like :

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

So basically you create an array that is containing all nodes in your tree indexed by parent which will be traversed in a recursive manner to determine the correct left and right values per node.

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



来源:https://stackoverflow.com/questions/2432725/php-moving-mysql-tree-node

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!