現在のページに基づいて子リンクを出力する方法


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、ごちゃごちゃしてすみません。私が使った解決策(私のコメントで参照)はここで使用されています:link。主な質問は次のとおりです:なぜmenu_build_tree()が予期しないレベルのネストされた配列を返すのですか(すべてのリンクが同じである必要があります)?子アイテムを表示している場所を確認するには、含めたリンクを使用して、メインのナビゲーションバーのリンクをクリックします(cssは、クリックできないようにするために使用されます)。
Chris Rockwell

モジュールに関しては、ざっと見ただけでは十分なものは何も見つかりませんでした。これは、4行または5行のコードで実行する必要があるソリューション用に別のモジュールをインストールすることにあまり興味がなかったためと考えられます。このようなものに使用するカスタムの「includes」モジュールがすでにあります。これで、どこからでも、電話をかけるだけget_sub_menu_based_on_active_page()で準備が整いました。cssはユーザーを賢くしないため、入れ子の問題を理解しようとすることから先に進む必要がありました。
Chris Rockwell

1
私は別のアプローチで回答投稿しました。これが最も簡単な解決策の1つだと思います。そして、それは正しく動作します。提案されたモジュールは、Drupalユーザーの間で本当に人気があります。
Sk8erPeter 2012

回答:


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()node / idを取得します。
mediaashley

6

メニューブロックモジュールを使用すると簡単に実行できます(構成に約5分かかります)。

メニューブロックのスクリーンショット

あなたがしなければならないすべては

  1. モジュールを有効にする
  2. に行く admin/structure/block
  3. 「メニューブロックの追加」をクリック
  4. [開始レベル]を[2番目のレベル(セカンダリ)]に設定し、[ このブロックを表示するテーマと領域を指定する]で表示する領域を設定します。

  5. スクリーンショット:

    • これは、設定ページが次のように見える方法です

      スクリーンショット

    • Menuブロックモジュールブロックが有効になっているadmin / structure / blockページ

      スクリーンショット

    • Develモジュールで「基本ページ」コンテンツを生成し、それらへのメニューリンクをいくつか提供して、ネストされたメニュー階層を作成しました

      • これは、サブメニューのないデフォルトのフロントページです(「メインメニュー-2番目のレベル」ブロックは、2番目のレベルの子アイテムがないため、左側のサイドバーに表示されません)。

      スクリーンショット

      • これは2番目のメニューで、いくつかの子要素があります。左側のサイドバーに「メインメニュー-2番目のレベル」が表示されていますが、2番目のレベルの子要素しか表示されていません。

        スクリーンショット

        第2レベルのアイテム

      • より深く行きます:

        第3レベルの子要素も表示されます

このタスクにMenuブロックモジュールを使用することは、最も簡単で最速のソリューションの1つだと思います。


私がこの投稿に反対票を投じた理由は本当に気になります。推奨されるモジュールがその役割を果たし、ステップバイステップのチュートリアルを書きました。なぜ反対投票者が理由のコメントを投稿しないのですか?(多分それは役に立つかもしれません(多分役に立たないかもしれません)、少なくとも反応する可能性があります。)
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

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

マリオありがとう。あなたが使用しての上にこれを選んだ理由についてコメントすることができます$parametersmenu_build_tree
Chris Rockwell、

フィードバックをお寄せいただきありがとうございます。何$parametersを使っても必要な情報が得られなかったので、よく見たと思います。私が欲しかったのは、パスを指定して、すべてのレベルのすべての子メニュー項目を取得することだけであり、方法を見つけることができませんでした。あれば、私に知らせてください。答えとブログ投稿を学び、更新できます。乾杯。
Mario Awad 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.