Come generare link secondari in base alla pagina corrente


10

Quando atterro su una pagina che ha una voce di menu che è genitore di altre voci di menu di pagine, vorrei poter mostrare un elenco di quelle voci di menu figlio. Sto usando il seguente codice.

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

Tuttavia, l'array restituito appare così (con molti inutili rimossi).

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)

Notate come 314, 315 e 316 sono "inferiori" a 312? Sono fratelli nella mia struttura di menu, e questo sembra essere verificato da ognuno con lo stesso valore per plid(311). Ovviamente posso risolvere questo problema passando l'array attraverso un'altra funzione, ma non posso fare a meno di pensare che mi manca qualcosa.


Nell'interesse del tempo, sto risolvendo il problema con CSS, anche se non sono contento. $tree = menu_build_tree('main-menu', array( 'expanded' => array($trail[1]['mlid']) )); drupal_render(menu_tree_output($tree))Quindi usando CSS posso modellare i collegamenti per rimuovere il ulriempimento, facendoli sembrare che siano tutti sullo stesso livello. Non ideale, ma efficace. EDIT: scusa, non riesco a capire come far funzionare le interruzioni di riga.
Chris Rockwell,

non potresti pubblicare uno screenshot di esempio di ciò che vorresti ottenere? Ad essere sincero, ho trovato la domanda un po 'confusa (ho il coraggio di dirlo perché non sono state ancora scritte risposte). Dove vorresti essere in grado di mostrare gli articoli figlio? Perché i moduli relativi al menu non sono soddisfacenti? Per favore, chiarisci un po 'di più la domanda e forse potremmo trovare una buona soluzione.
Sk8erPeter

@ Sk8erPeter, mi scuso se è disordinato. La soluzione che ho scelto (citata nel mio commento) viene utilizzata qui: link . La domanda principale è: perché menu_build_tree () restituisce un array nidificato con livelli imprevisti (tutti i collegamenti dovrebbero essere sullo stesso)? Per vedere dove sto mostrando gli elementi figlio, usa il link che ho incluso e fai clic su qualsiasi link nella barra di navigazione principale (css è usato per dare l'illusione che non siano cliccabili).
Chris Rockwell,

Per quanto riguarda i moduli, uno sguardo superficiale non ha rivelato nulla che fosse sufficiente. Ciò potrebbe essere dovuto al fatto che non ero molto interessato all'installazione di un altro modulo per una soluzione che dovrebbe essere realizzata in 4 o 5 righe di codice. Ho già un modulo "include" personalizzato che uso per cose come questa. Ora, da qualsiasi luogo, chiamo get_sub_menu_based_on_active_page()e sono pronto. Ho dovuto passare dal tentativo di capire il problema della nidificazione poiché il CSS rende l'utente più saggio.
Chris Rockwell,

1
Ho pubblicato una risposta con un altro approccio, penso che sia una delle soluzioni più semplici. E funziona correttamente. Il modulo suggerito è molto popolare tra gli utenti di Drupal.
Sk8erPeter

Risposte:


8

Volevo solo dare un seguito. Sono tornato a questa domanda e ho trovato quanto segue: /programming/2716787/how-to-get-all-the-menu-items-below-a-certain-parent-in-drupal che è esattamente quello di cui avevo bisogno.

Il codice, copiato dal link sopra menzionato e modificato per soddisfare le mie esigenze (principalmente per utilizzare il percorso corrente da cui creare la struttura del menu, anziché utilizzare un valore hardcoded:

$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
Funziona bene, ma dovresti usare current_path()invece di $_GET['q']. $_GET['q']restituirà l'alias del percorso, dove current_path()otterrà il nodo / id.
mediaashley,

6

Può essere fatto facilmente usando il modulo Blocco menu (ci vogliono circa 5 minuti per configurarlo).

Schermata del blocco menu

Tutto quello che devi fare è

  1. Abilitazione del modulo
  2. Andando a admin/structure/block
  3. Facendo clic su "Aggiungi blocco menu"
  4. Impostare "Livello iniziale" su "2 ° livello (Secondario)" e impostare la regione in cui dovrebbe essere visualizzato in "Specificare in quali temi e regioni viene visualizzato questo blocco."

  5. Screenshots:

    • Questo è l'aspetto della pagina di configurazione

      immagine dello schermo

    • pagina admin / struttura / blocco con i blocchi modulo blocco menu abilitati

      immagine dello schermo

    • Ho generato alcuni contenuti della "Pagina di base" con il modulo Devel, ho fornito alcuni collegamenti ai menu e ho creato una gerarchia di menu nidificata

      • Questa è la prima pagina predefinita senza sottomenu (il blocco "Menu principale - 2 ° livello" NON può essere visto nella barra laterale di sinistra, poiché non ha elementi secondari di secondo livello)

      immagine dello schermo

      • Questo è il secondo menu, con alcuni elementi figlio, puoi già vedere il "Menu principale - 2 ° livello" nella barra laterale di sinistra, ma solo gli elementi figlio di 2 ° livello sono visibili

        immagine dello schermo

        oggetti di secondo livello

      • Ora approfondendo:

        Si possono vedere anche elementi figlio di terzo livello

Penso che l'utilizzo del modulo Blocco menu per questa attività sia una delle soluzioni più semplici e veloci.


Sarei davvero curioso di sapere perché ho ottenuto un voto negativo per questo post. Il modulo consigliato fa il lavoro e ho scritto un tutorial passo-passo. Perché il downvoter non pubblica un commento sui motivi? (Forse sarebbe utile (forse no), potrei almeno reagire.)
Sk8erPeter

0

Come notato nei commenti, ho finito per usare la funzione API e quindi lo styling con 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

Funziona correttamente per ottenere il sottomenu della pagina corrente:

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

Spero che questo aiuto!


La tua funzione chiama una funzione non definita (override_left_l)!
DrCord,

0

@ Chris Rockwell e @ Mario Awad

Sono un novizio in Drupal, quindi è difficile capire per me dove aggiungere questa funzione .. Mi scuso per quello. Ragazzi, potete per favore menzionarlo in quale file, dovremmo aggiungere questa funzione?

Sto cercando di creare una barra di navigazione che visualizzerà solo elementi figlio su ogni pagina. Come creare un menu di navigazione sulla barra laterale con diversi collegamenti di navigazione visualizzati su pagine diverse?

Apprezzo!

Grazie!


0

Ho appena finito di pubblicare una funzione che ottiene le voci di menu figlio in base al percorso di un nodo. Puoi verificarlo qui: http://softkube.com/blog/getting-child-menu-items-drupal-menu-tree

Sto includendo il link per la prova futura della risposta nel caso in cui il post venga aggiornato e alla fine copierò / incollerò il codice completo.

Nel tuo caso, puoi semplicemente eseguire qualcosa di simile nel tuo tema per elencare tutte le voci di menu figlio. Modifica l' echoaffermazione e il tema a tuo piacimento.

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

Ed ecco il codice completo della funzione. Controlla il link per eventuali futuri aggiornamenti.

In bocca al lupo.

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

Grazie Mario. Puoi commentare il motivo per cui hai scelto questa opzione usando $parametersin menu_build_tree?
Chris Rockwell,

Grazie per il feedback. Non sono riuscito a ottenere le informazioni necessarie, indipendentemente da quello che $parametersho usato, e credetemi, ho guardato molto. Tutto quello che volevo è, dato un percorso, ottenere tutte le voci di menu figlio su tutti i livelli e semplicemente non riuscivo a trovare un modo. Se ce n'è uno, ti prego di informarmi che sarò felice di imparare e aggiornare la mia risposta e il mio post sul blog. Saluti.
Mario Awad,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.