Торговец знаниями
Уважаемые, подскажите.
Дано: таблица, содержит в себе дерево (дерево сделано на основе nested sets aka вложенные множества).
Требуется: пример кода для перемещения произвольного узла (возможно, вместе с поддеревом) в произвольную позицию дерева.
С остальными операциями разобрался, а вот с перемещением — не получается.
Есть прекрасная статья, но вот конкретно момент с перемещением узлов там крайне мутно написан.

@темы: MySQL, PHP

Комментарии
17.02.2008 в 15:59

Будем же учиться хорошо мыслить - вот основной принцип морали (с) Паскаль
Я не совсем так представляю себе структуру таблицы. ИМХО - гораздо удобнее, если добавить еще поля parent_id и fix для блокировки записей. Тогда функцию переноса можно оформить как-то так:



<?

function MoveNode($nodeId$parentId) {

    global 
$db;

   
$row $db->selectRow("SELECT id FROM tbl WHERE id = ?d"$nodeId);
   
$targetRow $db->selectRow("SELECT id FROM tbl WHERE id = ?d"$parentId);

   
//фиксируем узел и поддерево, а заобно получаем количство дочерних узлов
   
$countChilds $db->query("UPDATE tbl SET fix = 1 WHERE left_id >= ?d AND right_id <= ?d",
       
$row['left_id'], $row['right_id']);

   
//обновляем записи
   
$db->query("UPDATE tbl SET left_id = left_id - ?d WHERE left_id > ?d AND fix = 0",
       
$countChilds 2$row['left_id']);
   
$db->query("UPDATE tbl SET right_id = right_id - ?d WHERE right_id > ?d AND fix = 0",
       
$countChilds 2$row['left_id']);

   
//обновляем записи правее вставляемого узла
   
$db->query("UPDATE tbl SET left_id = left_id + ?d WHERE left_id > ?d AND fix = 0",
       
$countChilds 2$targetRow['left_id']);
   
$db->query("UPDATE tbl SET right_id = right_id + ?d WHERE right_id > ?d AND fix = 0",
       
$countChilds 2$targetRow['left_id']);

   
//вставляем узел и обновляем элементы поддерва перемещаемого узла
   
$db->query("UPDATE tbl SET parent_id = ?d WHERE id = ?d"$parentId$nodeId);
   
$db->query("UPDATE tbl SET left_id = left_id + ?d, right_id = right_id + ?d, level = level + ?d WHERE fix = 1",
       
$targetRow['left_id'] - $row['left_id'] + 1$targetRow['level'] - $row['level'] +
       
1);

   
//снимаем фиксацию
   
$db->query("UPDATE tbl SET fix = 0 WHERE fix = 1");
}

?>






PS: работа с БД идет через класс DBSimple, Дмитрия Котерова.
PPS: функцию не тестировал =)
17.02.2008 в 19:16

Торговец знаниями
Ну, общая мысль верная, но немного не так. Спасибо, очень помог, натолкнул на верный ход мысли. :)
В чём, собственно, разница: я не хочу ставить перемещаемый узел первым потомком, а наоборот, есть желание поставить его последним. Соответственно изменяются вычисления на обновлении узлов, относящихся к поддереву перемещаемого узла.
17.12.2016 в 19:05

А конкретно рабочий код для перемещения узлов с вложенными узлами в другие подузлы, есть? Буду очень благодарен

Расширенная форма

Редактировать

Подписаться на новые комментарии
Получать уведомления о новых комментариях на E-mail