Я кодю кое-чего крупное на CakePHP. Ну то есть код с нуля, а базы кое-какие остались от прошлой системы. И есть в этих базах дерево категорий. Обычное иерархическое дерево, где у каждого элемента есть parent_id:
id name parent_id
1 first 0
2 second 0
3 third 1
Случилось так, что в CakePHP есть встроенный функционал для работы с деревьями, но работает он только для структур вида nested sets. Что это такое довольно хорошо описано здесь.
Итак, на данном этапе сформировалась задача перевести существующее дерево к виду nested sets, а это значит у каждой записи в таблице проставить значения left и right. Гуглению было посвящено около часа. Сплошные вопросы, и ни одного работающего решения. Собственно такое положение и явилось причиной, по которой я выкладываю свою функцию. Вникайте.
$table = 'categories';
$number=1;
make_nested(0);
function make_nested($parent_id = 0) {
global $db, $table, $number;
$c = $db->selectCell("SELECT COUNT(*) from ".$table." \
where parent_id=".$parent_id."");
for($i=0; $i< $c; $i++) {
$newrow = $db->selectRow("SELECT * FROM ".$table." \
where parent_id=".$parent_id." order by sort, id \
LIMIT $i, 1");
$db->query("UPDATE `".$table."` SET lft=".$number." \
WHERE id=".$newrow['id']."");
$number++;
make_nested($newrow['id']);
$db->query("UPDATE `".$table."` SET rght=".$number." \
WHERE id=".$newrow['id']."");
$number++;
}
}
Собственно функция — это как бы тот самый “червячок”, обходящий все вершины против часовой и размечающий их. Ничего сложного. Пользуйтесь и радуйтесь!