За последние 24 часа нас посетили 20708 программистов и 1715 роботов. Сейчас ищут 1390 программистов ...

Построение многоуровневого меню.

Тема в разделе "PHP для профи", создана пользователем xaker01, 1 окт 2017.

  1. xaker01

    xaker01 Активный пользователь

    С нами с:
    16 апр 2016
    Сообщения:
    210
    Симпатии:
    34
    Знаю что эта тема замусолена в просторах рунета и не только, но за 30 часов решения так и не нашел.
    Переспрашивал и перегуглил всех кого мог, обычно используют функции mysql для этого,что тоже не для меня.
    Вариант с each тоже отпадает, так как с php 7.2 он больше не рабочий.
    А мне проект поддерживать еще не 1 год.


    Вот сама задача.
    Должна быть навигация с вложенностью N раз.

    имеется массив $categories с полями last_id,id, итд
    для примера

    PHP:
    1. $array = array();
    2. $array[] = array('id'=>8,    'pid'=>4,    'header'=>'H');
    3. $array[] = array('id'=>1,    'pid'=>0,    'header'=>'A');
    4. $array[] = array('id'=>11,    'pid'=>10,    'header'=>'M');
    5. $array[] = array('id'=>10,    'pid'=>5,    'header'=>'L');
    6. $array[] = array('id'=>9,    'pid'=>5,    'header'=>'K');
    7. $array[] = array('id'=>4,    'pid'=>0,    'header'=>'D');
    8. $array[] = array('id'=>12,    'pid'=>9,    'header'=>'N');
    9. $array[] = array('id'=>5,    'pid'=>1,    'header'=>'E');
    10. $array[] = array('id'=>7,    'pid'=>3,    'header'=>'G');
    11. $array[] = array('id'=>3,    'pid'=>0,    'header'=>'C');
    12. $array[] = array('id'=>2,    'pid'=>0,    'header'=>'B');
    13. $array[] = array('id'=>6,    'pid'=>1,    'header'=>'F');
    нужно его собрать, и вывести.

    Что я делал.
    PHP:
    1. function getTree($categories, $depth = '0')
    2.     {
    3.         $array = array();
    4.         foreach ($categories as $cat) {
    5.             if ($cat['pid'] == $depth) {
    6.                 $cats[]=CategoriesModel::getTree($categories, $cat['id']);
    7.                 $array[] = array_merge($array, $cats);
    8.  
    9.             }
    10.         }
    11.  
    12.         return $array;
    13.     }

    Вроде бы все и отлично, но когда делаю var_dump или через цикл пропускаю результат.
    Имеем пустоту.
    HTML:
    1. Array
    2. (
    3.     [0] => Array
    4.         (
    5.             [0] => Array
    6.                 (
    7.                     [0] => Array
    8.                         (
    9.                             [0] => Array
    10.                                 (
    11.                                     [0] => Array
    12.                                         (
    13.                                             [0] => Array
    14.                                                 (
    15.                                                 )
    16.  
    17.                                         )
    18.  
    19.                                     [1] => Array
    20.                                         (
    21.                                             [0] => Array
    22.                                                 (
    23.                                                     [0] => Array
    24.                                                         (
    25.                                                         )
    26.  
    27.                                                 )
    28.  
    29.                                             [1] => Array
    30.                                                 (
    31.                                                 )
    32.  
    33.                                             [2] => Array
    34.                                                 (
    35.                                                 )
    36.  
    37.                                         )
    38.  
    39.                                     [2] => Array
    40.                                         (
    41.                                             [0] => Array
    42.                                                 (
    43.                                                     [0] => Array
    44.                                                         (
    45.                                                         )
    46.  
    47.                                                 )
    48.  
    49.                                             [1] => Array
    50.                                                 (
    51.                                                     [0] => Array
    52.                                                         (
    53.                                                             [0] => Array
    54.                                                                 (
    55.                                                                 )
    56.  
    57.                                                         )
    58.  
    59.                                                     [1] => Array
    60.                                                         (
    61.                                                         )
    62.  
    63.                                                     [2] => Array
    64.                                                         (
    65.                                                         )
    66.  
    67.                                                 )
    68.  
    69.                                             [2] => Array
    70.                                                 (
    71.                                                 )
    72.  
    73.                                             [3] => Array
    74.                                                 (
    75.                                                 )
    76.  
    77.                                             [4] => Array
    78.                                                 (
    79.                                                 )
    80.  
    81.                                         )
    82.  
    83.                                     [3] => Array
    84.                                         (
    85.                                             [0] => Array
    86.                                                 (
    87.                                                     [0] => Array
    88.                                                         (
    89.                                                         )
    90.  
    91.                                                 )
    92.  
    93.                                          
    94.                                  
    95.  
    96.                                             итд
    97.                                                 (

    В отчаянии прошу вашей помощи, наставлением, и примерами для такой задачи если вы их реализовывали.
    Желательно современные решения)
     
    #1 xaker01, 1 окт 2017
    Последнее редактирование: 1 окт 2017
  2. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    Я для этих целей использовал одну таблицу в бд с такой структурой:
    Код (Text):
    1. CREATE TABLE `category` (
    2.   `id` int(11) NOT NULL,
    3.   `parent_category` int(11) DEFAULT NULL,
    4.   `name` varchar(200) NOT NULL,
    5.   `description` varchar(1000) NOT NULL
    6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    7.  
    8. --
    9. -- Dumping data for table `category`
    10. --
    11.  
    12. INSERT INTO `category` (`id`, `parent_category`, `name`, `description`) VALUES
    13. (1, NULL, 'Посуда', 'Декоративная посуда, тарелки и все такое'),
    14. (2, 1, 'Тарелки', 'Тарелки круглые квадратные'),
    15. (3, 1, 'Рюмки', 'Рюмки всех видов'),
    16. (4, NULL, 'Электроника', 'Сотовые телефоны, умные часы а так остальная электроника'),
    17. (5, 2, 'Блюдницы', 'Тарелки для блюд и сервировки стола');
    18.  
    19. --
    20. -- Indexes for dumped tables
    21. --
    22.  
    23. --
    24. -- Indexes for table `category`
    25. --
    26. ALTER TABLE `category`
    27.   ADD PRIMARY KEY (`id`);
    28.  
    29. --
    30. -- AUTO_INCREMENT for dumped tables
    31. --
    32.  
    33. --
    34. -- AUTO_INCREMENT for table `category`
    35. --
    36. ALTER TABLE `category`
    37.   MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
    Теперь выборка:

    PHP:
    1. //демонстрация
    2. echo "<br>";
    3. foreach ($categoryes as $val) {
    4.     if (is_null($val['parent_id'])) {
    5.         echo $val['name'] . "<br>";
    6.         foreach ($categoryes as $val1) {
    7.             if ($val['id'] == $val1['parent_id']) {
    8.                 echo "--" . $val1['name'] . "<br>";
    9.             }
    10.         }
    11.     }
    12. }
    И все, получаем свое меню.

    Важно:
    код будет работать только с PHP-версией выше 7
    --- Добавлено ---
    Допустима любая вложеность.
     
    xaker01 нравится это.
  3. xaker01

    xaker01 Активный пользователь

    С нами с:
    16 апр 2016
    Сообщения:
    210
    Симпатии:
    34
    Отлично, мне нравится способ, вроде и без рекурсии.
    Конечно при тесте 3 уровень вложенности не работал, и должен ли работать.
    Ладно сейчас еще протестирую, базу чуть иначе сделаю.
    А так рад буду и другим примерам.
     
  4. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    @xaker01, третий тоже работал вроде. Вообще, я думаю о рекурсии. Мне не нравится что столько циклов требуется если увеличивать вложенность.
     
    xaker01 нравится это.
  5. xaker01

    xaker01 Активный пользователь

    С нами с:
    16 апр 2016
    Сообщения:
    210
    Симпатии:
    34
    а так вот в чем дело) для 3 вложенности нужен новый цикл), я думал нашел вариант без него)
    тут без рекурсии не обойтись ни как., так что я в эту сторону тоже копаю.
    У меня потом задача еще веселе, сортировка выводить 1 категорию, или 2 , и также субкатегорию, и суб -суб.... категорию.
     
  6. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    PHP:
    1. function test($categoryes, $category_id = NULL) {
    2.     foreach ($categoryes as $category) {
    3.         if (is_null($category['parent_id']) && is_null($category_id)) {
    4.             echo "<ul><li>" . $category['name'] . '</li>';
    5.             test($categoryes, $category['id']);
    6.         } else if ($category['parent_id'] == $category_id) {
    7.             echo "<ul><li>" . $category['name'] . '</li>';
    8.             test($categoryes, $category['id']);
    9.         }
    10.     }
    11.     echo "</ul>";
    12. }
    остается стилизовать. Но я бы всеравно использовал циклы если не нужны вложенности более трех.))
    --- Добавлено ---
    PHP:
    1. //использование
    2. test($categories);
     
  7. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    PHP:
    1. function getTree($categories, $pid = 0){
    2.     $tree = [];
    3.     foreach($categories as $k=>$v){
    4.         if($v['pid'] == $pid){
    5.             unset($categories[$k]);
    6.             $tree[] = [
    7.                 'id' => $v['id'],
    8.                 'pid' => $v['pid'],
    9.                 'header' => $v['header'],
    10.                 'childs' => getTree($categories, $v['id']),
    11.             ];
    12.         }
    13.     }
    14.     return $tree;
    15. }
    16.  
    17. echo '<pre>';
    18. print_r(getTree($array));
    19. echo '</pre>';
    --- Добавлено ---
    а вот таже самая рекурсия но для постройки li списка

    Код (Text):
    1. function buildLiTree($categories, $pid = 0){
    2.     $string = '<ul>';
    3.     foreach($categories as $k=>$v){
    4.         if($v['pid'] == $pid){
    5.             unset($categories[$k]);
    6.             $string .= '<li>';
    7.             $string .= '<a href=' . $v['id'] . '>' . $v['header'] . '</a>';
    8.             $tmp = buildLiTree($categories, $v['id']);
    9.             $string .= strpos($tmp, 'li') ? $tmp : '';
    10.             $string .= '</li>';
    11.         }
    12.     }
    13.     $string .= '</ul>';
    14.     return $string;
    15. }
    16.  
    17. echo buildLiTree($array);
     
    xaker01 нравится это.
  8. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
  9. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    пытался я когда то сделать с нестет сетсами)) потом плюнул и сделал через pid))
     
    xaker01 нравится это.
  10. xaker01

    xaker01 Активный пользователь

    С нами с:
    16 апр 2016
    Сообщения:
    210
    Симпатии:
    34
    я тоже через pid, другие способы , скажем не очень.

    Кстати твой способ полностью сработал)
    Прям точь в точь как надо..

    Осталось только все это в библеотеку хорошую оформить и все)