Понадобилось реализовать некоторые ORM-модели с поддержкой алгоритма Nested Sets, поэтому решил посмотреть существующие разработки. Существует проект MPTT library на официальной странице проектов Kohana, но меня в данный момент эта библиотека не устраивает отсутствием поддержки нескольких деревьев (multiple scopes), а также реализацией запросов к БД напрямую, без использования Query Builder‘а. На code.google.com есть проект ORM_MPTT, но он давно не развивается (что не помешало именно этой библиотеке стать отправной точкой для всех последующих разработок алгоритма Nested Sets под Kohana).
В результате я решил пойти по стопам разработчика S7Ncms (Eduard Baun) — сделать собственную библиотеку с реализацией нужных мне методов. Первая версия библиотеки доступна здесь. [подумываю насчет установки redmine для собственных проектов на сайт, реально ли это?]
Redmine? Смотря на сколько сильное желание будет
Я неделю на своем мучался, пока настроил так, что меня стало устраивать и компьютер не умирал под нагрузками при коммитах. Можете написать мне в личку — дам ссылку на свой, посмотрите, как выглядит «домашний» Redmine.
Интересно, можете на почту скинуть? Вообще пользую хостинг проектов от Google, но как-то хочется свое поставить. Правда, смущают возможные неприятные нагрузки…
PS. Блог сами разработали? На Yii, как я понимаю
Вы не могли бы выложить исходники своей библиотеки еще раз в доступное место? По указанной ссылке только: Unknown post id, it may have expired or been deleted …
Не хватает наверное еще в библиотеке методов перемещения нодов между собой, а так реализация достойная, только в 349 строке имя метода исправьте, видимо ошибка.
Переместить узел с дочерними элементами можно методом move_to(). Также можно сменить родителя у всех дочерних элементов текущего узла (move_chilren_to()). Или надо что-то другое?
Какая ошибка в строке 349? neighbor = ‘сосед’, метод проверяет, общий ли у них родитель.
В 349 у вас метод обзывается is_heighbor
А не хватает метода, который бы менял позиции нодов между собой
http://php.russofile.ru/ru/authors/sql/nestedsets01
Вот на мой взгляд один из самых развитых классов для работы с деревьями. (методы ChangePosition и ChangePositionAll)
Ну, по сути это последовательные два вызова move_to(). Можно их реализовать в одном (уменьшится количество запросов), но часто ли они применяются?
PS. А по поводу метода is_neighbor() все равно не понял
Как Вы предлагаете его обозвать?
is_heighbor != is_neighbor() , просто у вас опечатка
Тьфу!
Спасибо, исправил.
методы ChangePosition и ChangePositionAll в принципе вещи достаточно часто применяемые — допустим для сортировки категорий в каталоге.
ИМХО, сортировка не имеет ничего общего с хранимыми в БД данными. Если сегодня одна категория выше, а завтра другая — постоянно менять их местами? Проще сделать дополнительное поле и сортировать (ORDER BY) по нему…
сортировка и иерархия хранимых данных вещи разные! но существуют как правило слитно — использование нестет деерва оправдано
, а ORDER BY может «максимум» выводить детей в меню, отсортированными по алфавиту, не нарушая структуры ИМХО 
Спасибо за ссылочку на DB Tree…
и Вам BlackaVeron, спасибо …
Представим себе две соседние ветки по 100 дочерних узлов в каждой. Чтобы поменять их местами, придется выполнить специальные (довольно затратные) запросы. А вот добавить к узлам поле order_num, которое будет управлять очередностью вывода веток — намного ведь проще. Разве не так? ИМХО, в пределах одного уровня ветки в принципе равнозначны, и не имеет смысла их менять местами (по крайней мере на стадии эксплуатации).
Хотя метод все равно надо будет добавить…
«Ну, по сути это последовательные два вызова move_to(). Можно их реализовать в одном (уменьшится количество запросов), но часто ли они применяются?»
например, есть дерево:
- level1
— level 1.1
— level 1.2
— level 1.3
— level 1.4
Как тогда с помощью move_to() поменять level 1.2 и level 1.3 местами?
Повторюсь, тут не имеет смысла реализовывать сортировку таким вот жестким способом. Добавьте к записи в БД поле «порядковый номер» (или «вес», или еще как-нибудь). Вместо того, чтобы менять узлы местами «физически» (т.е. меняя их поля left и right), достаточно поменять значения данных полей. Не забывайте, что ветки 1.2 и 1.3 могут содержать достаточное количество дочерних узлов, а это увеличит количество обновляемых записей.
А вот перенести ветку в совсем другое место дерева (не в пределах одного общего родительского узла) — это да, имеет смысл. Но обычно при этом обмена не происходит, переносится только одна ветвь.
Все это, конечно, мое ИМХО.
Я считаю, что когда дело касается админки, то можно позволить себе непристойность выполнять запросы посложнее, нежели в пользовательской части.
В чём один из люсов left_key и right_key у Nested Sets? Да в том, что по left_key как раз и можно делать сортировку ORDER BY!
Да, плюс достаточно существенный, чтобы с ним считаться…
Насчет перемещения узла относительно другого — как есть метод insert_near(). Ну, и все идет к тому, что скоро появится метод exchange($node1, $node2)
PS. Правда, на данный момент я использую Ko3, так что навряд ли смогу быстро обновить класс для 2.3.4.
А я вчера написал метод position уже для твоего класса. Поделюсь с миром в ближайшее время
Да, выглядит так:
$item = $tree->find($id);
$item->position($near_id, ‘auto|before|after’);
Разумеетя, $id и $near_id потомки одного родителя одного и того же уровня.