PHP移动mySQL树节点

时间:2010-03-12 12:40:48

标签: php mysql tree nodes

我在尝试向上或向下移动子节点或父节点时遇到了麻烦...不太擅长数学。

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文本NOT NULL,
  page-content文本NOT NULL,
  page-time int(11)unsigned NOT NULL,   page-slug文本NOT NULL,
  page-template文本NOT NULL,
  page-parent mediumint(8)未签名   NOT NULL,page-type text NOT NULL,   主要钥匙(page-id))   ENGINE = MyISAM DEFAULT CHARSET = latin1   ;

     

INSERT INTO pagespage-id,   page-leftpage-right,   page-titlepage-content,   page-timepage-slug,   page-templatepage-parent,   page-type)价值观(17,1,6,'1',   '',0,'父母','',0,''),(18,2,   5,'2','',0,'SUB','',17,''),   (19,3,4,'3','',0,'SUB-SUB','',   18,''),(20,7,8,'5','',0,   'TEST','',0,'');

作为示例,我如何在PARENT之上移动TEST并说通过使用页面左/页右ID来将SUB移动到SUB-SUB下面?代码不仅仅需要帮助SQL概念或数学,它将帮助我理解如何更好地移动它...

1 个答案:

答案 0 :(得分:3)

所以基本上你想将邻接列表转换为嵌套集?首先更新邻接列表(即将page_parent值更新为新树的正确值),然后运行下面的转换。

使用PHP(基本代码,未经测试):

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
        ...
    }
}

当你调用它时,$ rawData应该包含一个ID数组,由parent-id索引,你可以创建它(基于你的表结构),如下所示($ db应该包含一个活动的PDO连接对象):

    $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;
    }

要进行转换,您需要以下内容:

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

所以基本上你创建一个数组,其中包含由父索引的树中的所有节点,这些节点将以递归方式遍历,以确定每个节点的正确左右值。

BTW您可以在纯SQL中执行此操作(在您调整表/列名称之后): http://bytes.com/topic/mysql/answers/638123-regenerate-nested-set-using-parent_id-structure