问题
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