Подтвердить что ты не робот

Лучшая древовидная структура php/Mysql

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

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

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

4b9b3361

Ответ 1

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

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

Некоторым может быть трудно понять концепции вложенных множеств слева и справа. Я обнаружил, что, используя эти числа в качестве аналогии для номеров строк тегов open/close в документе 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>

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

Ответ 2

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

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

Ответ 3

            <?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),'</pre>';

            // display menu
            echo themeMenu($menu,1);

            /*
            * ------------------------------------------------------------------------------------
            * Utility functions
            * ------------------------------------------------------------------------------------
            */

            /*
            * Convert adjacency list to hierarchical tree
            *
            * @param value of root level parent most likely null or 0
            * @param array result
            * @param str name of primary key column
            * @param str name of parent_id column - most likely parent_id
            * @param str name of index that children will reside ie. children, etc
            * @return array tree
            */
            function convertAdjacencyListToTree($intParentId,&$arrRows,$strIdField,$strParentsIdField,$strNameResolution) {

                $arrChildren = array();

                for($i=0;$i<count($arrRows);$i++) {
                    if($intParentId === $arrRows[$i][$strParentsIdField]) {
                        $arrChildren = array_merge($arrChildren,array_splice($arrRows,$i--,1));
                    }
                }

                $intChildren = count($arrChildren);
                if($intChildren != 0) {
                    for($i=0;$i<$intChildren;$i++) {
                        $arrChildren[$i][$strNameResolution] = convertAdjacencyListToTree($arrChildren[$i][$strIdField],$arrRows,$strIdField,$strParentsIdField,$strNameResolution);
                    }
                }

                return $arrChildren;

            }

            /*
            * Theme menu
            *
            * @param array menu
            * @param runner (depth)
            * @return str themed menu
            */
            function themeMenu($menu,$runner) {

                $out = '';

                if(empty($menu)) {
                    return $out;
                }

                $out.='<ul>';
                foreach($menu as $link) {
                    $out.= sprintf(
                        '<li class="depth-%u">%s%s</li>'
                        ,$runner
                        ,$link['name']
                        ,themeMenu($link['links'],($runner+1))
                    );
                }

                $out.='</ul>';
                return $out;

            }

            ?>