현재 페이지를 기반으로 하위 링크를 출력하는 방법


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에 만족하지는 않지만 CSS로 문제를 해결하고 있습니다. $tree = menu_build_tree('main-menu', array( 'expanded' => array($trail[1]['mlid']) )); drupal_render(menu_tree_output($tree))그런 다음 CSS를 사용하여 링크의 스타일을 지정하여 ul패딩 을 제거하여 모두 동일한 레벨에 표시되도록 할 수 있습니다. 이상적이지는 않지만 효과적입니다. 편집 : 죄송합니다, 줄 바꿈이 작동하는 방법을 알 수 없습니다.
Chris Rockwell

달성하고자하는 샘플 스크린 샷을 게시 할 수 없습니까? 솔직히 말해서, 나는 질문이 약간 지저분하다는 것을 알았습니다 (아직 답변이 작성되지 않았기 때문에 그 말을 감히합니다). 하위 항목을 어디에 표시 할 수 있습니까? 메뉴 관련 모듈이 만족스럽지 않은 이유는 무엇입니까? 질문을 조금 더 명확히하면 좋은 해결책을 찾을 수 있습니다.
Sk8erPeter

@ Sk8erPeter, 지저분한 지 사과드립니다. 내가 갔던 해결책 (내 의견에서 참조)은 여기에서 사용됩니다 : link . 주요 질문은 다음과 같습니다. menu_build_tree ()가 예기치 않은 수준의 중첩 배열을 반환하는 이유는 무엇입니까 (모든 링크는 동일해야 함)? 하위 항목을 표시하는 위치를 확인하려면 포함 된 링크를 사용하고 기본 탐색 모음에서 링크를 클릭하십시오 (css는 클릭 할 수없는 환상을주는 데 사용됨).
Chris Rockwell

모듈과 관련하여, 한 눈에보기에 충분하지 않은 것은 없습니다. 4 ~ 5 줄의 코드로 달성 해야하는 솔루션을 위해 다른 모듈을 설치하는 데 관심이 없었기 때문일 수 있습니다. 이미 이와 같은 용도로 사용하는 사용자 정의 '포함'모듈이 있습니다. 이제 어디서나 전화를 get_sub_menu_based_on_active_page()하고 모든 준비를 마쳤습니다. CSS가 사용자를 더 현명하게 만들지 않기 때문에 중첩 문제를 알아 내려고 노력해야했습니다.
Chris Rockwell

1
내가 대답을 게시 다른 접근 방식을, 그 가장 쉬운 솔루션 중 하나라고 생각합니다. 그리고 제대로 작동합니다. 제안 된 모듈은 Drupal 사용자들 사이에서 정말 인기가 있습니다.
Sk8erPeter

답변:


8

후속 조치를 원했습니다. 이 질문에 돌아와서 다음 발견 /programming/2716787/how-to-get-all-the-menu-items-below-a-certain-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()노드 / ID를 가져옵니다.
mediaashley

6

메뉴 블록 모듈 을 사용하여 쉽게 수행 할 수 있습니다 (구성하는 데 약 5 분 소요).

메뉴 블록 스크린 샷

당신이해야 할 일은

  1. 모듈 활성화
  2. 가는 중 admin/structure/block
  3. "메뉴 블록 추가"를 클릭
  4. "시작 레벨"을 "2 차 레벨 (2 차)"로 설정하고 "이 블록이 표시되는 테마 및 영역을 지정하십시오"에서 표시 될 영역을 설정하십시오 .

  5. 스크린 샷 :

    • 이것이 구성 페이지의 모습입니다

      스크린 샷

    • 활성화 된 메뉴 블록 모듈 블록이있는 관리자 / 구조 / 블록 페이지

      스크린 샷

    • Devel 모듈로 일부 "기본 페이지"컨텐츠를 생성하고 이에 대한 일부 메뉴 링크를 제공하고 중첩 된 메뉴 계층 구조를 작성했습니다.

      • 하위 메뉴가없는 기본 프론트 페이지입니다 ( "메인 메뉴-2 차 레벨"블록은 2 차 레벨 하위 항목이 없으므로 왼쪽 사이드 바에 표시되지 않습니다).

      스크린 샷

      • 이것은 하위 요소가있는 두 번째 메뉴입니다. 왼쪽 사이드 바에 "기본 메뉴-2 단계"가 이미 표시되어 있지만 2 단계 하위 요소 만 표시됩니다.

        스크린 샷

        2 단계 아이템

      • 이제 더 깊이가 :

        3 단계 하위 요소도 볼 수 있습니다

이 작업에 메뉴 블록 모듈을 사용 하는 것이 가장 쉽고 빠른 솔루션 중 하나 라고 생각합니다 .


이 게시물에 대한 공감대를 얻은 이유가 정말 궁금합니다. 권장 모듈이 작업을 수행하며 단계별 자습서를 작성했습니다. 다운 보터가 이유에 대한 의견을 게시하지 않는 이유는 무엇입니까? (아마도 도움이 될지 모르지만, 적어도 반응 할 수는 있습니다.)
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

@Chris Rockwell과 @ Mario Awad

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?
Chris Rockwell

피드백을 주셔서 감사합니다. 내가 무엇 $parameters을 사용 하든 필요한 정보를 얻을 수 없었고 , 많이 보았다고 믿습니다. 내가 원하는 것은 경로가 주어지면 모든 수준의 모든 하위 메뉴 항목을 얻는 것이므로 방법을 찾을 수 없었습니다. 답변이 있으면 답변과 블로그 게시물을 배우고 업데이트하게되어 기쁩니다. 건배.
Mario Awad
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.