So geben Sie untergeordnete Links basierend auf der aktuellen Seite aus

10

Wenn ich auf einer Seite lande, deren Menüelement anderen Menüelementen übergeordnet ist, möchte ich eine Liste dieser untergeordneten Menüelemente anzeigen können. Ich verwende den folgenden Code.

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

Das zurückgegebene Array sieht jedoch so aus (wobei viele unnötige entfernt werden).

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)

Beachten Sie, wie 314, 315 und 316 unter 312 liegen. Sie sind Geschwister in meiner Menüstruktur, und das scheint von jedem überprüft zu werden, der den gleichen Wert für plid(311) hat. Natürlich kann ich das beheben, indem ich das Array durch eine andere Funktion leite, aber ich kann nicht anders, als zu glauben, dass mir nur etwas fehlt.

Chris Rockwell
quelle
Im Interesse der Zeit behebe ich das Problem mit CSS, obwohl ich damit nicht zufrieden bin. $tree = menu_build_tree('main-menu', array( 'expanded' => array($trail[1]['mlid']) )); drupal_render(menu_tree_output($tree))Dann kann ich mithilfe von CSS die Links so gestalten, dass die ulAuffüllung entfernt wird, sodass sie alle auf derselben Ebene liegen. Nicht ideal, aber effektiv. EDIT: Entschuldigung, ich kann nicht herausfinden, wie Zeilenumbrüche funktionieren.
Chris Rockwell
Können Sie keinen Beispiel-Screenshot von dem veröffentlichen, was Sie erreichen möchten? Um ehrlich zu sein, fand ich die Frage etwas chaotisch (ich wage es zu sagen, weil noch keine Antworten geschrieben wurden). Wo möchten Sie die untergeordneten Elemente anzeigen können? Warum sind die menübezogenen Module nicht zufriedenstellend? Bitte klären Sie die Frage etwas genauer, und vielleicht könnten wir eine gute Lösung finden.
Sk8erPeter
@ Sk8erPeter, ich entschuldige mich, wenn es chaotisch ist. Die Lösung, die ich gewählt habe (auf die in meinem Kommentar verwiesen wird), wird hier verwendet: Link . Die Hauptfrage lautet: Warum gibt menu_build_tree () ein verschachteltes Array mit unerwarteten Ebenen zurück (alle Links sollten sich auf derselben befinden)? Um zu sehen, wo ich die untergeordneten Elemente zeige, verwenden Sie den von mir angegebenen Link und klicken Sie auf einen beliebigen Link in der Hauptnavigationsleiste (CSS wird verwendet, um die Illusion zu vermitteln, dass sie nicht anklickbar sind).
Chris Rockwell
In Bezug auf die Module ergab ein flüchtiger Blick nichts, was ausreichen würde. Das könnte daran liegen, dass ich nicht sehr daran interessiert war, ein anderes Modul für eine Lösung zu installieren, die in 4 oder 5 Codezeilen ausgeführt werden sollte. Ich habe bereits ein benutzerdefiniertes Includes-Modul, das ich für solche Dinge verwende. Jetzt rufe get_sub_menu_based_on_active_page()ich von überall an und bin fertig. Ich musste nicht mehr versuchen, das Verschachtelungsproblem herauszufinden, da CSS den Benutzer nicht klüger macht.
Chris Rockwell
1
Ich habe eine Antwort mit einem anderen Ansatz gepostet. Ich denke, das ist eine der einfachsten Lösungen. Und es funktioniert richtig. Das vorgeschlagene Modul ist bei Drupal-Benutzern sehr beliebt.
Sk8erPeter

Antworten:

8

Ich wollte nur nachfassen. Ich kam auf diese Frage zurück und fanden die folgende: /programming/2716787/how-to-get-all-the-menu-items-below-a-certain-parent-in-drupal das ist genau das, was ich brauchte.

Der Code, der über den oben genannten Link kopiert und an meine Anforderungen angepasst wurde (hauptsächlich, um den aktuellen Pfad zum Erstellen des Menübaums zu verwenden, anstatt einen fest codierten Wert zu verwenden:

$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>';
Chris Rockwell
quelle
1
Dies funktioniert gut, aber Sie sollten current_path()anstelle von verwenden $_GET['q']. $_GET['q']gibt den Pfadalias zurück, wobei current_path()Knoten / ID abgerufen wird.
Mediaashley
6

Die Verwendung des Menüblockmoduls ist problemlos möglich (die Konfiguration dauert ca. 5 Minuten).

Screenshot des Menüblocks

Alles was du tun musst, ist

  1. Modul aktivieren
  2. Ich gehe zu admin/structure/block
  3. Klicken Sie auf "Menüblock hinzufügen".
  4. Stellen Sie "Startebene " auf "2. Ebene (Sekundär)" und legen Sie die Region fest, in der sie angezeigt werden soll, unter "Geben Sie an, in welchen Themen und Regionen dieser Block angezeigt wird".

  5. Screenshots:

    • So sieht die Konfigurationsseite aus

      Bildschirmfoto

    • Admin / Struktur / Block Seite mit den aktivierten Menüblock Modulblöcken

      Bildschirmfoto

    • Ich habe mit dem Devel-Modul einige Inhalte der "Basisseite" generiert, einige Menüverknüpfungen zu diesen bereitgestellt und eine verschachtelte Menühierarchie erstellt

      • Dies ist die Standard-Startseite ohne Untermenüs (Der Block "Hauptmenü - 2. Ebene" ist NICHT in der linken Seitenleiste zu sehen, da er keine untergeordneten Elemente der zweiten Ebene enthält.)

      Bildschirmfoto

      • Dies ist das zweite Menü, mit einigen untergeordneten Elementen können Sie bereits das "Hauptmenü - 2. Ebene" in der linken Seitenleiste sehen, aber nur die untergeordneten Elemente der 2. Ebene werden angezeigt

        Bildschirmfoto

        Gegenstände der zweiten Ebene

      • Jetzt tiefer gehen:

        Untergeordnete Elemente der dritten Ebene können ebenfalls angezeigt werden

Ich denke, dass die Verwendung des Menüblockmoduls für diese Aufgabe eine der einfachsten und schnellsten Lösungen ist.

Sk8erPeter
quelle
Ich wäre wirklich neugierig, warum ich eine Ablehnung für diesen Beitrag bekommen habe. Das empfohlene Modul erledigt den Job und ich habe eine Schritt-für-Schritt-Anleitung geschrieben. Warum gibt der Downvoter keinen Kommentar zu den Gründen ab? (Vielleicht wäre es nützlich (vielleicht auch nicht), ich könnte zumindest reagieren.)
Sk8erPeter
0

Wie in den Kommentaren erwähnt, habe ich schließlich die API-Funktion verwendet und dann mit CSS gestylt:

/* --------------- *\
    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%;
}
Chris Rockwell
quelle
0

Diese Funktion funktioniert ordnungsgemäß, um das Untermenü der aktuellen Seite aufzurufen:

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

Ich hoffe das hilft!

Xman Klassik
quelle
Ihre Funktion ruft eine undefinierte Funktion auf (override_left_l)!
DrCord
0

@ Chris Rockwell und @ Mario Awad

Ich bin ein Neuling in Drupal, daher ist es für mich schwer zu verstehen, wo ich diese Funktion hinzufügen soll. Ich entschuldige mich dafür. Aber könnt ihr bitte erwähnen, dass wir in welcher Datei diese Funktion hinzufügen sollen?

Ich versuche, eine Seitenleisten-Navigation zu erstellen, die nur untergeordnete Elemente auf jeder Seite anzeigt. Wie erstelle ich ein Navigationsmenü in der Seitenleiste mit verschiedenen Navigationslinks, die auf verschiedenen Seiten angezeigt werden?

Ich schätze!

Vielen Dank!

Vidushi
quelle
0

Ich habe gerade eine Funktion veröffentlicht, die untergeordnete Menüelemente mit dem Pfad eines Knotens abruft. Sie können es hier überprüfen: http://softkube.com/blog/getting-child-menu-items-drupal-menu-tree

Ich füge den Link zur Zukunftssicherung der Antwort hinzu, falls der Beitrag aktualisiert wird, und ich werde am Ende auch den vollständigen Code kopieren / einfügen.

In Ihrem Fall können Sie einfach so etwas in Ihrem Thema ausführen, um alle untergeordneten Menüelemente aufzulisten. Ändern Sie die echoAussage und das Thema nach Ihren Wünschen.

$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 />';
}

Und hier ist der vollständige Code der Funktion. Überprüfen Sie den Link auf mögliche zukünftige Updates.

Viel Glück.

/**
 * 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;
}
Mario Awad
quelle
Danke Mario. Können Sie kommentieren, warum Sie dies der Verwendung von $parametersin menu_build_treevorgezogen haben?
Chris Rockwell
Danke für die Rückmeldung. Ich konnte nicht die benötigten Informationen bekommen, egal was $parametersich benutzte, und glauben Sie mir, ich sah viel aus. Ich wollte nur einen Pfad erhalten, alle untergeordneten Menüpunkte auf allen Ebenen abrufen, und ich konnte einfach keinen Weg finden. Wenn es eine gibt, informiere mich bitte. Ich werde froh sein, meine Antwort und meinen Blog-Beitrag zu erfahren und zu aktualisieren. Prost.
Mario Awad