php / Mysql лучшая древовидная структура - PullRequest
19 голосов
/ 07 мая 2011

Мне нужно построить дерево, в котором будет около 300 узлов.Дерево не имеет ограничений по глубине.Так что может иметь 3 или 15 уровней.Каждый узел может иметь неограниченное количество дочерних элементов.

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

Я хочу знать, как лучше всего хранить дерево в базе данных, и как лучше всего получать данные, если это возможно, в php.

Ответы [ 3 ]

71 голосов
/ 07 мая 2011

Вы можете использовать Модель вложенного набора , поскольку она дает очень эффективные запросы. Изучите Управление иерархическими данными в MySQL и прочитайте раздел под названием Модель вложенного набора .

Если вы используете ORM, такой как Doctrine, включает возможности вложенного набора .

Некоторым может быть трудно понять понятия вложенного множества влево и вправо. Я обнаружил, что использование этих чисел в качестве аналогии для номеров строк открытия / закрытия теги в XML-документе, людям легче понять.

Например, возьмите пример данных из ссылки MySQL выше:

+-------------+----------------------+-----+-----+
| category_id | name                 | lft | rgt |
+-------------+----------------------+-----+-----+
|           1 | ELECTRONICS          |   1 |  20 |
|           2 | TELEVISIONS          |   2 |   9 |
|           3 | TUBE                 |   3 |   4 |
|           4 | LCD                  |   5 |   6 |
|           5 | PLASMA               |   7 |   8 |
|           6 | PORTABLE ELECTRONICS |  10 |  19 |
|           7 | MP3 PLAYERS          |  11 |  14 |
|           8 | FLASH                |  12 |  13 |
|           9 | CD PLAYERS           |  15 |  16 |
|          10 | 2 WAY RADIOS         |  17 |  18 |
+-------------+----------------------+-----+-----+

Если вы возьмете поля lft , rgt и будете использовать их в качестве номеров строк для документа XML, вы получите:

1. <electronics>
2.    <televisions>
3.        <tube>
4.        </tube>
5.        <lcd>
6.        </lcd>
7.        <plasma>  
8.        </plasma> 
9.     </televisions>
10.    <portable electronics>
11.        <mp3 players>
12.            <flash>
13.            </flash>
14.        </mp3 players>
15.        <cd players>
16.        </cd players>
17.        <2 way radios>
18.        </2 way radios>
19.    </portable electronics>
20. </electronics>

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

7 голосов
/ 07 мая 2011

Это отличная статья об этом: Управление иерархическими данными в MySQL .Я использовал в течение долгого времени.

Если у вас есть некоторые математические возможности, вы действительно можете понять, почему это так здорово!

0 голосов
/ 08 июля 2016
<code>            <?php

            $host = "localhost";
            //Database user name.   
            $login = "root";
            //Database Password.
            $dbpass = "";
            $dbname = "abc";
            $PDO = new PDO("mysql:host=localhost;dbname=$dbname", "$login", "$dbpass");
            $rows = array();
            $sql = 'SELECT id, parent_id, name FROM employee';
            $query = $PDO->prepare($sql);
            $query->execute();
            $rows = array();

                if (!$query)
                {
                    $error = 'Error fetching page structure, for nav menu generation.';
                    exit();
                }

            while($row = $query->fetch(PDO::FETCH_ASSOC)){
                if( strcasecmp($row['parent_id'],'null') === 0 || empty($row['parent_id']) ) {
                     $row['parent_id'] = null;
                }

                $rows[] = $row;
            }


            // covert raw result set to tree
            $menu = convertAdjacencyListToTree(null,$rows,'id','parent_id','links');
            // echo '<pre>',print_r($menu),'
';// отображение меню echo themeMenu ($ menu, 1);/ * * ------------------------------------------------------------------------------------ * Функции утилит * ------------------------------------------------------------------------------------ * / / * * Преобразовать список смежности в иерархическое дерево * * @param значение родительского уровня корневого уровня, скорее всего, ноль или 0* @param array result * @param str имя столбца первичного ключа * @param str имя столбца parent_id - наиболее вероятно parent_id * @param str имя индекса, в котором будут находиться дочерние элементы, т.е.дети и т. д. * @return массив деревьев * / функция convertAdjacencyListToTree ($ intParentId, & $ arrRows, $ strIdField, $ strParentsIdField, $ strNameResolution) {$ arrChildren = array ();для ($ I = 0; $ я% s% s ', $ runner, $ link [' name '], themeMenu ($ link [' links '], ($ runner + 1)));} $ out. = '';вернуть $ out;}?>
...