如何根据当前页面输出子链接


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 2012年

@ Sk8erPeter,很麻烦,我深表歉意。我使用的解决方案(在我的评论中引用)在这里使用:link。主要问题是:为什么menu_build_tree()返回具有意外级别的嵌套数组(所有链接应该在同一位置)?要查看我在哪里显示子项,请使用我包含的链接,然后单击导航栏上的任何链接(css用于提供无法点击的错觉)。
克里斯·罗克韦尔

关于这些模块,粗略地浏览并没有发现任何足以满足要求的内容。那可能是因为我对为应该用4或5行代码完成的解决方案安装另一个模块不是很感兴趣。我已经有一个自定义的“包含”模块,可用于此类操作。现在,我可以从任何地方打电话get_sub_menu_based_on_active_page()给我,一切准备就绪。我不得不继续尝试解决嵌套问题,因为CSS使用户变得更明智。
克里斯·罗克韦尔

1
我用另一种方法发布了答案,我认为这是最简单的解决方案之一。而且它可以正常工作。推荐的模块在Drupal用户中非常受欢迎。
Sk8erPeter 2012年

Answers:


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 2014年

6

使用菜单块模块可以轻松完成(配置大约需要5分钟)。

菜单块截图

您要做的就是

  1. 启用模块
  2. 即将 admin/structure/block
  3. 点击“添加菜单栏”
  4. 将“起始级别”设置为“第二级(第二级)”,并在“指定此块显示在哪些主题和区域中”下设置应显示的区域。

  5. 屏幕截图:

    • 这是配置页的样子

      屏幕截图

    • 带有已启用的菜单块模块块的admin / structure / block页面

      屏幕截图

    • 我使用Devel模块生成了一些“基本页面”内容,并提供了一些菜单链接,并创建了一个嵌套的菜单层次结构

      • 这是默认的首页,没有子菜单(“ Main menu-2nd level”(主菜单-第二级)块在左侧边栏中无法看到,因为它没有任何第二级子项)

      屏幕截图

      • 这是第二个菜单,带有一些子元素,您已经可以在左侧边栏中看到“主菜单-第二级”,但是只能看到第二级子元素

        屏幕截图

        二级物品

      • 现在更深入:

        也可以看到三级子元素

我认为将菜单块模块用于此任务是最简单,最快的解决方案之一。


我真的很好奇,为什么我对此文章不满意。推荐的模块可以完成工作,我编写了分步教程。为什么下降投票者不对原因发表评论?(也许会很有用(也许没有),我至少可以做出反应。)
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 2014年


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;
}

谢谢马里奥。您能否评论为什么选择使用$parametersin menu_build_tree呢?
克里斯·罗克韦尔

感谢您的反馈。无论使用什么$parameters方式,我都无法获得所需的信息,并且相信我看起来很不错。我所想要的就是给定路径,在所有级别上获得所有子菜单项,而我根本找不到方法。如果有,请通知我,我将很高兴学习和更新我的答案和博客文章。干杯。
Mario Awad 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.