За последние 24 часа нас посетили 18329 программистов и 1582 робота. Сейчас ищет 1121 программист ...

Вывод дерева категорий с разной разметкой.

Тема в разделе "Решения, алгоритмы", создана пользователем Deonis, 7 дек 2017.

  1. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Приветствую! Предположим ситуацию:
    1. Дерево может выводиться, как горизонтальное выпадающее меню
    2. Может быть, например, вертикальное, аккордеон
    3. Может быть, как dropdown с <optgroup>.
    Как-то раньше не парился по этому поводу. Делал трейт с несколькими методами, каждый из которых генерировал ту или иную разметку и возвращал уже сформированный HTML с заранее определенными классами, id-шниками и другими атрибутами.
    Теперь предположим, что хозяин решил изменить дизайн. В таком случае, верстальщику придётся лезть в код трейта и править HTML прямо там. Хорошо, если он с прямыми руками и имеет достаточное представление о PHP, а если нет? Вот я и задумался, как можно было бы подключать в трейте определенный файл шаблона и на его основе формировать дерево, но с идеями пока печаль, т.к. методы рекурсивные и в зависимости от того, есть или нет дочерние категории, разметка будет разной, да и классы родительских элементов, могут отличаться от дочерних.
    Может кто уже решал подобную задачу и поделиться принципами её реализации?

    P.S. Единственная мысля, которая сегодня меня посетила - это передавать в методы массив с атрибутами. Но этот массив тоже должен откуда-то браться. Делать отдельный конфигурационный файл для таких задач? Тоже как-то не комильфо и не факт, что верстальщик сам поймет, где и куда вносить изменения.
     
  2. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    Думал о чем то подобном не так давно.
    Можно всегда выдавать один и тот же html (многоуровневый ul li),
    но по разному реализовывать css.
    Максимум, что должно различаться в html - это класс коренного ul
    --- Добавлено ---
    остальное - магия селекторов
     
  3. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Я даже приблизительно это не могу себе представить. Набросал простейший пример. Как сюда, по вашему совету, можно подключать шаблон с одним и тем же html?
    PHP:
    1. <?php
    2. $category= [
    3.   1 =>
    4.     [
    5.       'parent_id' => 0,
    6.       'category_name' => 'Parent 1',
    7.       'sub' =>
    8.         [
    9.           2 =>
    10.             [
    11.               'parent_id' => 1,
    12.               'category_name' => 'Child 1.1',
    13.             ],
    14.           5 =>
    15.             [
    16.               'parent_id' => 1,
    17.               'category_name' => 'Child 1.2',
    18.               'sub' =>
    19.                 [
    20.                   6 =>
    21.                     [
    22.                       'parent_id' => 5,
    23.                       'category_name' => 'Child 1.2.1',
    24.                     ],
    25.                 ],
    26.             ],
    27.         ],
    28.     ],
    29.   3 =>
    30.     [
    31.       'parent_id' => 0,
    32.       'category_name' => 'Parent 2',
    33.       'sub' =>
    34.         [
    35.           4 =>
    36.             [
    37.               'parent_id' => 3,
    38.               'category_name' => 'Child 2.1',
    39.             ],
    40.         ],
    41.     ],
    42. ];
    43. function treeHtml($data) {
    44.   $result = [];
    45.   if (!empty($data)) {
    46.     $result[] = '<ul>';
    47.     foreach ($data as $entry) {
    48.       $result[] = sprintf(
    49.         '<li>%s %s</li>',
    50.         $entry['category_name'],
    51.         (!empty($entry['sub']) ? treeHtml($entry['sub']) : '')
    52.       );
    53.     }
    54.     $result[] = '</ul>';
    55.   }
    56.   return implode('', $result);
    57. }
    58.  
    59. echo treeHtml($category);
     
  4. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    вот, что я имел в виду.
    два одинаковы html с разными классами у коренного ul.
    Две разные менюшки.
    И с этими стилями может быть неограниченное количество вложений.
    Мой велосипед)

    а последнего вопроса не понял. Функция же вроде генерирует нормальный html
     
  5. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Как раз в этом и была вся суть. Не просто генерировать HTML, а использовать подготовленный шаблон.
    В общем, появилась у меня одна мысль, чуть позже попробую. Общая идея в том, чтобы распарсить шаблон с учетом вложенности элементов, вытащив в массив сами элементы и их атрибуты, а в цикле (опять же ориентируясь на текущий уровень вложенности) просто подставлять необходимые элементы с атрибутами, ну и данные из базы: имена категорий, где нужно ссылки генерировать и т.д. Будет свободное время - попробую и отпишусь.
     
  6. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Не надо отдавать html, надо просто подготовить и отдать набор данных. Что с ними произойдет в шаблоне и как оно будет отображено - совершенно другой вопрос. Всё )
     
  7. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Многозначительно ))
    Ну, вот выше я показал подготовленный набор данных - массив с деревом. Отдаём в шаблон. Как выводить будем?
     
  8. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Как шаблон решит, так и будет выводить. Данным то какая разница? У них задача одна - быть достаточными для генерации страницы по шаблону.
    --- Добавлено ---
    Короче, давай ещё раз.

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

    Данные не должны решать как им отображаться, там нет и не может быть html. С другой стороны, представление это не html`ка с встроенными переменными, у него тоже может быть своя логика, оно даже может быть отдельным приложением. Просто не надо смешивать одно с другим и сразу станет проще )
     
    Maputo нравится это.
  9. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Похоже, что вы меня не понимаете и говорим мы о разном.
    Я говорю о том, что в шаблоне может быть разная структура и селекторы элементов. В мои планах - сформировать данные на основе этого шаблона. Т.е. Шаблон может быть такой:
    HTML:
    1. <ul id="list accordion">
    2.     <li class="item toggle">
    3.         <ul class="sub_list">
    4.             <li class="sub_item" data-id="{{id}}"><li class="fa fa-icon"><li> {{name}}</li>
    5.         </ul>
    6.     </li>
    7. </ul>
    А может быть таким
    HTML:
    1. <ul id="list">
    2.     <li class="item">
    3.         <ul class="sub_list">
    4.             <li class="sub_item">
    5.                 <a href="{{href}}">{{name}}</a>
    6.             </li>
    7.         </ul>
    8.     </li>
    9. </ul>
    Я хочу во вьюшке подхватывать этот шаблон и на его основе генерировать дерево с учетом структуры, классов и т.д. Пока остановился на идее, которую описал выше. Будет время - опробую. Другим вариантом, который рассматриваю - это передача на рендеринг массива: теги (ul, ol), id или классы для разных уровней, дополнительные атрибуты, возможные вложенные элементы и т.д. Но этот вариант, как мне кажется, будет очень громоздкий.
     
  10. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    эта задача, для верстальщика, решается на css, как в моём примере по ссылке
    если он такой верстальщик, что не знает ни php ни css, то нахер такой верстальщик нужен

    и у меня ощущение, что ты решаешь задачу, которая еще не возникла)
     
  11. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Да, так и есть. Иногда возникают мысли и на перспективку их прорабатываю, чтобы когда понадобиться, уже были под рукой разные варианты. К тому же, это помогает немного отдохнуть/переключиться от того, чем занимаешься в текущий момент.
     
  12. Maputo

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

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    Приведенная структура шаблона - та которая используется сейчас или планируется сделать ее такой?
     
  13. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    От фонаря набросал. Да и не имеет значения какая она будет. В принципе, ничего сложного я пока не вижу. Всю структуру можно разобрать с помощью xml_parse_into_struct или же отдельные компоненты DOMDocument + DOMXpath и т.д. А дальше дело техники ))
    --- Добавлено ---
    А в самом шаблоне, в нужном месте, что-то типа:
    PHP:
    1. View::tree->render('path/to/myTree.tpl');
     
  14. Maputo

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

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    Я использую похожую структуру. За отображение отвечает один класс (точнее его потомки). Все файлы представления хранятся в html формате, чтобы по-умолчанию работала подсветка html. И вместо <?php echo $some_data ?> используются метки типа %some_data%. Содержимое извлекается при помощи file_get_contents() и при помощи preg_replace_callback() метки заменяются на нужное содержимое из массива, наследуемого и заполняемого в потомке.
    Например при переключении на версию для слабовидящих я просто использую html страницу с другой версткой и для элементов новостей тоже другой шаблон - без фоток.
     
  15. SQLPowerUser

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

    С нами с:
    11 дек 2017
    Сообщения:
    5
    Симпатии:
    1
    Не знаю, поможет, нет...

    1. Вариант таблицы с группировками. На сервере генерим простейшую таблицу вида <tr><td>...<tr><td> (стандартом разрешено не закрывать теги <tr> <td> <li>, экономия процессора/трафика :))
    Далее несложный, но универсальный алгоритм на JavaScript сделает количество уровней по желанию. Пример: https://jsfiddle.net/NZaw4/194/embedded/result/
    Исходники: https://jsfiddle.net/NZaw4/194/

    2. Алгоритм группировки на PHP: http://programmersforum.ru/showthread.php?t=303535
     
  16. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    @SQLPowerUser, спасибо, но предложенное вами решение, никак не относится к сути вопроса.

    P.S. JS-код - ужасен. Хотя, если он писа́лся лет пять назад, то можно на это закрыть глаза ;)