Основным преимуществом данного метода является доступ к дочерним узлам любого уровня в один запрос к БД (правда с INNER JOIN).
Пример:
необходимо в разделе /company/ добраться до списка новостей (item1, item2)
Данные хранятся в таблицах со следующей структурой:
paths — дерево с путями
path_have_childs — таблица ссылок, хранит список дочерних узлов с уровнями относительно родительского узла
Данные — таблица с путями:
Дополнительная таблица — хранилище уровней дочернего узла относительно родительского:
Запрос генерирующий дополнительную таблицу для уровней — для каждого узла находятся все дочерние узлы, даже те которые не являются непосредственно дочерними, и вычисляется уровень вложенности относительно текущего узла:
Выбор всех дочерних узлов узла X (parent_have_childs.parent_id) с уровнем Y (parent_have_childs.level):
Конструктивные комментарии и критика приветствуются…
Пример:
необходимо в разделе /company/ добраться до списка новостей (item1, item2)
- /company/ О компании
- /company/news/ Новости
- /company/news/item2/ Вторая новость
- /company/news/item1/ Первая новость новость
- /company/history/ История
- /company/contacts/ Контакты
- /company/news/ Новости
Данные хранятся в таблицах со следующей структурой:
paths — дерево с путями
id
parent_id # хранится id родителя (paths.id)
name # имя узла, уникальное в пределах одного уровня
path # путь (/company/, /company/news/item1/)
title # для наглядности
path_have_childs — таблица ссылок, хранит список дочерних узлов с уровнями относительно родительского узла
parent_id # id родительского узла (paths.id)
child_id # id дочернего узла (paths.id)
level # уровень дочернего узла относительно родительского
Данные — таблица с путями:
id | parent_id | name | path | title |
---|---|---|---|---|
1 | 0 | / | Главная | |
2 | 1 | company | /company/ | О компании |
4 | 2 | news | /company/news/ | Новости |
5 | 4 | item1 | /company/news/item1/ | Новость 1 |
6 | 4 | item2 | /company/news/item2/ | Новость 2 |
3 | 1 | catalogue | /catalogue/ | Каталог |
7 | 3 | category1 | /catalogue/category1/ | Категория 1 |
8 | 7 | category2 | /catalogue/category1/category2/ | Категория 2 |
Дополнительная таблица — хранилище уровней дочернего узла относительно родительского:
parent_id | child_id | level |
---|---|---|
1 | 2 | 1 |
1 | 8 | 3 |
1 | 7 | 2 |
1 | 6 | 3 |
1 | 5 | 3 |
1 | 4 | 2 |
1 | 3 | 1 |
2 | 5 | 2 |
2 | 6 | 2 |
2 | 4 | 1 |
3 | 7 | 1 |
3 | 8 | 2 |
4 | 6 | 1 |
4 | 5 | 1 |
7 | 8 | 1 |
Запрос генерирующий дополнительную таблицу для уровней — для каждого узла находятся все дочерние узлы, даже те которые не являются непосредственно дочерними, и вычисляется уровень вложенности относительно текущего узла:
INSERT INTO path_have_childs
SELECT
P.id AS parent_id,
C.id AS child_id,
(LENGTH(C.path) - LENGTH(REPLACE(C.path,'/','')))
- (LENGTH(P.path) - LENGTH(REPLACE(P.path,'/','')))
FROM paths AS P
INNER JOIN paths AS C ON (C.path LIKE CONCAT(P.path, '_%'))
Выбор всех дочерних узлов узла X (parent_have_childs.parent_id) с уровнем Y (parent_have_childs.level):
SELECT C.path
FROM path_have_childs AS PHC
INNER JOIN paths AS C ON (PHC.child_id = C.id)
WHERE
PHC.level = Y
AND PHC.parent_id = X
Конструктивные комментарии и критика приветствуются…