Как вывести дочерние ссылки на основе текущей страницы


10

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

$trail = menu_get_active_trail();
menu_build_tree('main-menu', array(
  'expanded' => array($trail[1]['mlid'])
));

Тем не менее, возвращенный массив выглядит следующим образом (с большим количеством ненужных удаленных).

array
'49950 PKY Truck Beauty 312' => 
array
  'link' => &
    array
      'menu_name' => string 'main-menu' (length=9)
      'mlid' => string '312' (length=3)
      'plid' => string '311' (length=3)
  'below' => 
    array
      '49952 Seminars 314' => 
        array
          'link' => &
            array
              'menu_name' => string 'main-menu' (length=9)
              'mlid' => string '314' (length=3)
              'plid' => string '311' (length=3)
      '50000 HDMA Breakfast 316' => 
        array
          'link' => &
            array
              'menu_name' => string 'main-menu' (length=9)
              'mlid' => string '316' (length=3)
              'plid' => string '311' (length=3)
      '50000 MATS Concert 315' => 
        array
          'link' => &
            array
              'menu_name' => string 'main-menu' (length=9)
              'mlid' => string '315' (length=3)
              'plid' => string '311' (length=3)

Заметьте, как 314, 315 и 316 «ниже» 312? Они - братья и сестры в моей структуре меню, и это, кажется, подтверждается каждым, имеющим одинаковое значение для plid(311). Очевидно, я могу это исправить, передав массив через другую функцию, но я не могу не думать, что просто что-то упустил.


В интересах времени я исправляю проблему с CSS, хотя я не доволен этим. $tree = menu_build_tree('main-menu', array( 'expanded' => array($trail[1]['mlid']) )); drupal_render(menu_tree_output($tree))Затем с помощью CSS я могу стилизовать ссылки, чтобы убрать ulотступы, чтобы они выглядели на одном уровне. Не идеально, но эффективно. РЕДАКТИРОВАТЬ: извините, я не могу понять, как заставить работать разрывы строк.
— Крис Роквелл

Не могли бы вы опубликовать пример скриншота того, что вы хотели бы достичь? Честно говоря, я нашел вопрос немного беспорядочным (смею сказать, потому что ответы еще не написаны). Где бы вы хотели, чтобы дети могли показывать предметы? Почему модули, связанные с меню, не удовлетворяют? Пожалуйста, уточните вопрос немного больше, и, возможно, мы могли бы найти хорошее решение.
— Sk8erPeter

@ Sk8erPeter, прошу прощения, если это грязно. Решение, которое я использовал (упомянуто в моем комментарии), используется здесь: ссылка . Основной вопрос: почему menu_build_tree () возвращает вложенный массив с неожиданными уровнями (все ссылки должны быть одинаковыми)? Чтобы увидеть, где я показываю дочерние элементы, используйте ссылку, которую я включил, и нажмите любую ссылку на главной навигационной панели (css используется, чтобы создать иллюзию, что на них нельзя нажимать).
— Крис Роквелл

Что касается модулей, беглый взгляд не нашел ничего, что было бы достаточно. Это может быть потому, что я не очень заинтересован в установке другого модуля для решения, которое должно быть выполнено в 4 или 5 строках кода. У меня уже есть собственный модуль «include», который я использую для подобных вещей. Теперь откуда угодно звоню get_sub_menu_based_on_active_page()и у меня все готово. Мне пришлось отказаться от попыток выяснить проблему с вложенностью, так как css делает пользователя не мудрее.
— Крис Роквелл

1
Я разместил ответ с другим подходом, я думаю, что это одно из самых простых решений. И это работает правильно. Предлагаемый модуль действительно популярен среди пользователей Drupal.
— Sk8erPeter

Ответы:


8

Просто хотел продолжить. Я вернулся к этому вопросу и обнаружил следующее: /programming/2716787/how-to-get-all-the-menu-items-below-a-sure-parent-in-drupal, который именно то, что мне было нужно.

Код, скопированный из вышеупомянутой ссылки и измененный в соответствии с моими потребностями (в основном для использования текущего пути для построения дерева меню, а не с использованием жестко заданного значения:

$parent = menu_link_get_preferred($_GET['q']);
$parameters = array(
  'active_trail' => array($parent['plid']),
  'only_active_trail' => FALSE,
  'min_depth' => $parent['depth']+1,
  'max_depth' => $parent['depth']+1,
  'conditions' => array('plid' => $parent['mlid']),
);

$children = menu_build_tree($parent['menu_name'], $parameters);

return '<div class="content-sub-menu content-padder">' . drupal_render(menu_tree_output($children)) . '</div>';

1
Это хорошо работает, но вы должны использовать current_path()вместо $_GET['q']. $_GET['q']вернет псевдоним пути, где current_path()получит узел / идентификатор.
— медиаашлей

6

Это легко сделать с помощью модуля «Блок меню» (его настройка занимает около 5 минут).

Скриншот блока меню

Все, что вам нужно сделать, это

  1. Включение модуля
  2. Собираюсь admin/structure/block
  3. Нажав «Добавить блок меню»
  4. Установите «Начальный уровень» на «2-й уровень (Вторичный)» и укажите регион, в котором он должен отображаться, в разделе «Укажите, в каких темах и регионах отображается этот блок».

  5. Скриншоты:

    • Так выглядит страница конфигурации

      Скриншот

    • Страница администратора / структуры / блока с включенными блоками модуля меню блока

      Скриншот

    • Я сгенерировал некоторое содержимое «Базовой страницы» с помощью модуля Devel, предоставил несколько ссылок на меню и создал иерархию вложенных меню.

      • Это титульная страница по умолчанию без подменю (блок «Главное меню - 2-й уровень» НЕ виден на левой боковой панели, поскольку у него нет дочерних элементов второго уровня)

      Скриншот

      • Это второе меню, с некоторыми дочерними элементами, вы уже можете видеть «Главное меню - 2-й уровень» на левой боковой панели, но видны только дочерние элементы 2-го уровня

        Скриншот

        предметы второго уровня

      • Теперь углубляясь:

        Также можно увидеть дочерние элементы третьего уровня

Я думаю, что использование модуля « Меню » для этой задачи - одно из самых простых и быстрых решений.


Мне было бы очень любопытно, почему я получил понижение на этот пост. Рекомендуемый модуль выполняет свою работу, и я написал пошаговое руководство. Почему downvoter не публикует комментарий о причинах? (Может быть, это будет полезно (может быть, нет), я мог бы по крайней мере реагировать.)
— Sk8erPeter

0

Как отмечалось в комментариях, я в конечном итоге использовал функцию API, а затем стилизацию с помощью CSS:

/* --------------- *\
    Sub-menus
    used on main pages
\* --------------- */
.content-sub-menu ul.menu {
  list-style: none;
  padding: 0;
  margin: 0;
}
.content-sub-menu > ul.menu {
  margin-bottom: 25px;
}
.content-sub-menu ul.menu a {
  font-size: 1.5em;
  padding: 10px;
  margin-top: 5px;
  display: inline-block;
  min-width: 33%;
}

0

Эта функция работает правильно, чтобы получить подменю текущей страницы:

function build_left_menu()
{
    global $language_url;
    static $use_theme = NULL;
// Get the entire main menu tree
    $left_menu_tree = menu_tree_all_data('main-menu'); // Your main menu
$left_menu_tree_values = array_values($left_menu_tree); //get value only
    $html = "<div id=\"sidemenu\"><ul id=\"side-nav\" class=\"side-nav-content\"><h3>In this section:</h3>";
foreach ($left_menu_tree_values as $index => $item) {
        $link = $item["link"];
        if ($index === 0) {
            $item_class = "first-item panel side-menu ";
        } else {
            $item_class = "panel side-menu ";
        }
        $options_anchor = array();
        if ($item["below"]) {
            $options_anchor = array("attributes" => array('class' => array('dropdown-toggle'),
                'data-toggle' => 'dropdown',
                'data-delay' => 1000,
                'data-close-others' => "false",
                'data-hover' => "dropdown",
            )
            );
        }
        // Merge in defaults.
        $options_anchor += array(
            'attributes' => array(),
            'html' => FALSE,
        );

        //Default needed class
        $options['attributes']['class'][] = 'subpage-link collapsed';
        // Append active class.
        if (($link['link_path'] == $_GET['q'] || ($link['link_path'] == '<front>' && drupal_is_front_page())) &&
            (empty($options_anchor['language']) || $options_anchor['language']->language == $language_url->language)) {
            if ($item["below"]) {
                foreach ($item["below"] as $item_below) {
                    $link_below = $item_below["link"];
                    $options_anchor = array();
                    $html .= "<li class='" . $item_class . "'>";
                    $html .= override_left_l($link_below['link_title'], $link_below['link_path'], $options_anchor).'</li>';
                }
            }
        }
    }
    $html .= "</ul></div>";
    return $html;
}

Надеюсь, это поможет!


Ваша функция вызывает неопределенную функцию (override_left_l)!
— DrCord

0

@ Крис Роквелл и @ Марио Авад

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

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

Я ценю!

Спасибо!


0

Я только что закончил публиковать функцию, которая получает дочерние элементы меню по заданному пути узла. Вы можете проверить это здесь: http://softkube.com/blog/getting-child-menu-items-drupal-menu-tree

Я включил ссылку на ответ на будущее, если сообщение будет обновлено, и я также скопирую / вставлю полный код в конце.

В вашем случае вы можете просто запустить что-то подобное в своей теме, чтобы вывести список всех дочерних пунктов меню. Измените echoвысказывание и тему по своему вкусу.

$path = current_path();
$nids = skl_get_all_menu_node_children_ids($path);
$children = node_load_multiple($nids);
foreach($children as $c) {
    echo $c->title . ': ' . url('node/' $c->nid) . '<br />';
}

А вот полный код функции. Проверьте ссылку на возможные будущие обновления.

Удачи.

/**
 * Returns node ids of all the child items, including children of children
 * on all depth levels, of the given node path. Returns an empty array
 * if any error occurs.
 * 
 * @param string $node_path
 * @return array
 */
function skl_get_all_menu_node_children_ids($node_path) {
    //Stop and return an empty array if node path is empty
    if(empty($node_path)) {
        return array();
    }

    //Init empty array to hold the results
    $nids = array();

    //Init parent keys. Check 'foreach' loop on parent keys for more info.
    $parent_keys = array('plid', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8', 'p9');

    //Collect menu item corresponding to this path to begin updates.
    //Reference: http://stackoverflow.com/a/11615338/136696
    //Note: we couldn't find a way to get the sub-tree starting from this item
    //only and hence we had to get the whole menu tree built and then loop on
    //the current item part only. Not so bad considering that Drupal will
    //most probably have the whole menu cached anyway.
    $parent_menu_item = menu_link_get_preferred($node_path);

    //Stop and return empty array if a proper current menu item couldn't be found
    if(empty($parent_menu_item['menu_name']) || empty($parent_menu_item['mlid'])) {
        return array();
    }

    //Init parent item mlid for easier usage since now we know it's not empty
    $parent_menu_item_mlid = $parent_menu_item['mlid'];

    //Build whole menu based on the preferred menu_name gotten from this item
    $menu = menu_build_tree($parent_menu_item['menu_name']);

    //Reset menu cache since 'menu_build_tree' will cause trouble later on after 
    //you call pathauto to update paths as it can only be called once. 
    //Check: https://www.drupal.org/node/1697570
    menu_reset_static_cache();

    //Init processing array. This will hold menu items as we process them.
    $menu_items_to_process = array();

    //First run to fill up the processing array with the top level items
    foreach($menu as $top_level_menu_item) {
        $menu_items_to_process[] = $top_level_menu_item;
    }

    //While the processing array is not empty, keep looping into lower
    //menu items levels until all are processed.
    while(count($menu_items_to_process) > 0) {
        //Pop the top item from the processing array
        $mi = array_pop($menu_items_to_process);

        //Get its node id and add it to $nids if it's a current item child
        //Note that $parent_keys contains all keys that drupal uses to
        //set a menu item inside a tree up to 9 levels.
        foreach($parent_keys as $parent_key) {
            //First, ensure the current parent key is set and also mlid is set
            if(!empty($mi['link']['mlid']) && !empty($mi['link'][$parent_key])) {
                //If the link we're at is the parent one, don't add it to $nids
                //We need this check cause Drupal sets p1 to p9 in a way you
                //can easily use to generate breadcrumbs which means we will
                //also match the current parent, but here we only want children
                if($mi['link']['mlid'] != $parent_menu_item_mlid) {
                    //Try to match the link to the parent menu item
                    if($mi['link'][$parent_key] == $parent_menu_item_mlid) {
                        //It's a child, add it to $nids and stop foreach loop.
                        //Link_path has the path to the node. Example: node/63.
                        if(!empty($mi['link']['link_path'])) {
                            $nids[] = str_replace('node/', '', 
                                      $mi['link']['link_path']);
                            break;
                        }
                    }
                }
            }
        }

        //Add its child items, if any, to the processing array
        if(!empty($mi['below']) && is_array($mi['below'])) {
            foreach($mi['below'] as $child_menu_item) {
                //Add child item at the beginning of the array so that when
                //we get the list of node ids it's sorted by level with
                //the top level elements first; which is easy to attain
                //and also useful for some applications; why not do it.
                array_unshift($menu_items_to_process, $child_menu_item);
            }
        }
    }

    //Return
    return $nids;
}

Спасибо Марио. Можете ли вы прокомментировать, почему вы выбрали это, используя $parametersв menu_build_tree?
— Крис Роквелл,

Спасибо за ответ. Я не мог получить необходимую информацию, независимо от того, что $parametersя использовал, и поверьте мне, я выглядел много. Все, что я хотел, это дать путь, получить все дочерние элементы меню на всех уровнях, и я просто не мог найти путь. Если есть, сообщите мне, я буду рад узнать и обновить мой ответ и сообщение в блоге. Приветствия.
— Марио Авад
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.