Получить все родительские / дочерние записи из базы данных на Laravel (иерархические данные)

У меня есть следующая упрощенная структура таблицы базы данных для унаследованной системы, похожей на тикеты.

messages
id         INT
parent_id  INT
content    TEXT
answer     TEXT
...

В списке я показываю все сообщения. При нажатии на сообщение отображается его ответ и т. Д.

Проблема в том, что теперь мне нужна структура списка всех родители а также Дети связанные с этим сообщением, а также положение этого сообщения в дереве. Как я могу получить их из базы данных?

Я использую Laravel, но сырой SQL также поможет мне найти направление.


Пример:

╔════╦═══════════╦════════════════════════╦═══════ ══════════╗
║ id ║ parent_id ║ содержание ║ ответ ║
╠════╬═══════════╬════════════════════════╬═══════ ══════════╣
║ 1 ║ NULL ║ Привет, у меня проблема ║ Я не могу помочь ║
║ 2 ║ 1 ║ Проблема сохраняется ║ Хорошо, что это? ║
║ 3 ║ 2 ║ Неважно, я понял ║ О, хорошо. ║
║ 4 ║ 3 ║ Проблема вернулась ║ Какая проблема? ║
║ 5 ║ 4 ║ Та же проблема снова ║ ... ║
╚════╩═══════════╩════════════════════════╩═══════ ══════════╝

При отображении сообщения с id = 4, Я должен быть в состоянии отобразить что-то вроде этого списка:

История сообщений:
— Привет у меня проблема
— Проблема сохраняется
— Неважно, я получил это
Проблема вернулась
— Та же проблема снова

Я мог думать только о цикле и нескольких выполнениях SQL-запросов для каждого родителя и потомка, который выглядит как запах кода.


ОБНОВИТЬ

Как заявил Даан, этот вопрос кажется дубликатом для Как создать MySQL иерархический рекурсивный запрос.

Однако я решил не удалять его, поскольку Раван только что ответил на него с помощью подхода Laravel, который помог мне решить проблему, поэтому я просто оставлю это здесь для дальнейшего использования.

5

Решение

Поскольку вы выполняете иерархические операции, вы должны использовать стратегию для сохранения и извлечения этих данных из вашей базы данных.

Один подход заключается в использовании Модель вложенного набора, это может сделать это легче.
У Laravel есть отличный пакет, который имеет дело с этим, называется etrepat / Баум, это также объясняет, как это работает, и я цитирую:

Теория позади, версия TL; DR

Простой способ визуализировать, как работает вложенный набор, — думать о родительском объекте, окружающем все
его потомков и его родителей, окружающих его и т. д. Итак, это дерево:

root
|_ Child 1
|_ Child 1.1
|_ Child 1.2
|_ Child 2
|_ Child 2.1
|_ Child 2.2

Можно визуализировать так:

 ___________________________________________________________________
|  Root                                                             |
|    ____________________________    ____________________________   |
|   |  Child 1                  |   |  Child 2                  |   |
|   |   __________   _________  |   |   __________   _________  |   |
|   |  |  C 1.1  |  |  C 1.2 |  |   |  |  C 2.1  |  |  C 2.2 |  |   |
1   2  3_________4  5________6  7   8  9_________10 11_______12 13  14
|   |___________________________|   |___________________________|   |
|___________________________________________________________________|

Числа представляют левую и правую границы. Стол тогда мог
выглядеть так:

id | parent_id | lft  | rgt  | depth | data
1 |           |    1 |   14 |     0 | root
2 |         1 |    2 |    7 |     1 | Child 1
3 |         2 |    3 |    4 |     2 | Child 1.1
4 |         2 |    5 |    6 |     2 | Child 1.2
5 |         1 |    8 |   13 |     1 | Child 2
6 |         5 |    9 |   10 |     2 | Child 2.1
7 |         5 |   11 |   12 |     2 | Child 2.2

Чтобы все дети родитель узел, ты

SELECT * WHERE lft IS BETWEEN parent.lft AND parent.rgt

Чтобы получить количество детей, это

(right - left - 1)/2

Чтобы получить узел и всех его предков, возвращаясь к корню, вы

SELECT * WHERE node.lft IS BETWEEN lft AND rgt

Как видите, запросы, которые будут рекурсивными и непомерно медленными
обычные деревья внезапно довольно быстро. Отличный, не так ли?

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]