Bagaimana cara menghasilkan tautan anak berdasarkan halaman saat ini

10

Saat mendarat di halaman yang memiliki item menu yang merupakan induk dari item menu halaman lain, saya ingin dapat menampilkan daftar item menu anak-anak itu. Saya menggunakan kode berikut.

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

Namun, array yang dikembalikan terlihat seperti ini (dengan banyak yang tidak perlu dihapus).

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)

Perhatikan bagaimana 314, 315, dan 316 'di bawah' 312? Mereka adalah saudara kandung dalam struktur menu saya, dan yang tampaknya diverifikasi oleh masing-masing memiliki nilai yang sama untuk plid(311). Jelas saya bisa memperbaikinya dengan melewati array melalui fungsi lain, tapi saya tidak bisa tidak berpikir saya hanya melewatkan sesuatu.

Chris Rockwell
sumber
Demi kepentingan waktu, saya memperbaiki masalah dengan CSS, meskipun saya tidak senang dengan itu. $tree = menu_build_tree('main-menu', array( 'expanded' => array($trail[1]['mlid']) )); drupal_render(menu_tree_output($tree))Kemudian menggunakan CSS saya bisa menata tautan untuk menghapus ulpadding, membuatnya tampak semuanya pada level yang sama. Tidak ideal, tetapi efektif. EDIT: maaf, saya tidak tahu cara mendapatkan jeda baris untuk bekerja.
Chris Rockwell
tidak bisakah Anda memposting tangkapan layar sampel dari apa yang ingin Anda capai? Sejujurnya, saya menemukan pertanyaan sedikit berantakan (saya berani mengatakan itu karena belum ada jawaban yang ditulis). Di mana Anda ingin dapat menunjukkan barang-barang anak? Mengapa modul terkait menu tidak memuaskan? Tolong jelaskan pertanyaannya sedikit lagi, dan mungkin kita bisa menemukan solusi yang baik.
Sk8erPeter
@ Sk8erPeter, saya minta maaf jika ini berantakan. Solusi yang saya gunakan (dirujuk dalam komentar saya) sedang digunakan di sini: tautan . Pertanyaan utamanya adalah: mengapa menu_build_tree () mengembalikan array bersarang yang memiliki level tak terduga (semua tautan harus sama)? Untuk melihat di mana saya menunjukkan item anak, gunakan tautan yang saya sertakan dan klik tautan apa saja di bilah nav utama (css digunakan untuk memberi ilusi bahwa barang tersebut tidak dapat diklik).
Chris Rockwell
Mengenai modul, pandangan sepintas tidak muncul apa pun yang akan cukup. Itu bisa jadi karena saya tidak terlalu tertarik untuk menginstal modul lain untuk solusi yang harus diselesaikan dalam 4 atau 5 baris kode. Saya sudah memiliki modul 'termasuk' khusus yang saya gunakan untuk hal-hal seperti ini. Sekarang, dari mana saja, saya menelepon get_sub_menu_based_on_active_page()dan saya siap. Saya harus pindah dari mencoba mencari tahu masalah bersarang sebagai css membuat pengguna tidak ada yang lebih bijak.
Chris Rockwell
1
Saya mengirim jawaban dengan pendekatan lain, saya pikir itu adalah salah satu solusi termudah. Dan itu bekerja dengan benar. Modul yang disarankan sangat populer di kalangan pengguna Drupal.
Sk8erPeter

Jawaban:

8

Hanya ingin tindak lanjut. Saya kembali ke pertanyaan ini dan menemukan yang berikut: /programming/2716787/how-to-get-all-the-menu-items-below-a-certain-parent-in-drupal yang merupakan persis apa yang saya butuhkan.

Kode, disalin dari tautan yang disebutkan di atas dan dimodifikasi agar sesuai dengan kebutuhan saya (terutama untuk menggunakan jalur saat ini untuk membangun pohon menu dari, daripada menggunakan nilai kode-keras:

$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
sumber
1
Ini bekerja dengan baik, tetapi Anda harus menggunakan current_path()bukan $_GET['q']. $_GET['q']akan mengembalikan path alias, di mana current_path()akan mendapatkan node / id.
mediaashley
6

Ini dapat dengan mudah dilakukan dengan menggunakan modul Blok menu (dibutuhkan sekitar 5 menit untuk mengkonfigurasinya).

Screenshot blok menu

Yang harus Anda lakukan adalah

  1. Mengaktifkan modul
  2. Pergi ke admin/structure/block
  3. Mengklik "Tambahkan blok menu"
  4. Tetapkan "Level awal" ke "Level 2 (Sekunder)" dan tetapkan wilayah tempat ditampilkannya di bawah "Tentukan di mana tema dan wilayah mana blok ini ditampilkan."

  5. Tangkapan layar:

    • Ini adalah tampilan halaman konfigurasi

      tangkapan layar

    • admin / struktur / blok halaman dengan blok modul Menu yang diaktifkan

      tangkapan layar

    • Saya membuat beberapa konten "Halaman dasar" dengan modul Devel, dan memberikan beberapa tautan menu kepadanya, dan membuat hierarki menu bersarang

      • Ini adalah halaman depan default tanpa submenu (Blok "Menu utama - tingkat 2" TIDAK dapat dilihat di bilah sisi kiri, karena tidak memiliki item anak tingkat kedua)

      tangkapan layar

      • Ini adalah menu kedua, dengan beberapa elemen anak, Anda sudah dapat melihat "Menu utama - tingkat 2" di bilah sisi kiri, tetapi hanya elemen anak tingkat 2 yang dapat dilihat.

        tangkapan layar

        item tingkat kedua

      • Sekarang masuk lebih dalam:

        Elemen anak tingkat ketiga juga bisa dilihat

Saya pikir menggunakan modul Menu blok untuk tugas ini adalah salah satu solusi termudah dan tercepat.

Sk8erPeter
sumber
Saya akan sangat ingin tahu mengapa saya mendapat downvote untuk posting ini. Modul yang direkomendasikan berfungsi, dan saya menulis tutorial langkah demi langkah. Mengapa downvoter tidak memposting komentar tentang alasannya? (Mungkin itu akan berguna (mungkin tidak), setidaknya saya bisa bereaksi.)
Sk8erPeter
0

Seperti disebutkan dalam komentar, saya akhirnya menggunakan fungsi API dan kemudian menata dengan 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%;
}
Chris Rockwell
sumber
0

Ini berfungsi dengan benar untuk mendapatkan sub-menu dari halaman saat ini:

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

Semoga bantuan ini!

Xman Klasik
sumber
Fungsi Anda memanggil fungsi yang tidak ditentukan (override_left_l)!
DrCord
0

Saya baru saja selesai memposting fungsi yang mendapatkan item menu anak diberi jalur simpul. Anda dapat memeriksanya di sini: http://softkube.com/blog/getting-child-menu-items-drupal-menu-tree

Saya menyertakan tautan ke bukti di masa depan, kalau-kalau posting diperbarui dan saya juga akan menyalin / menempelkan kode lengkap di akhir.

Dalam kasus Anda, Anda dapat menjalankan sesuatu seperti ini di tema Anda untuk mendaftar semua item menu anak. Ubah echopernyataan dan tema sesuai keinginan Anda.

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

Dan inilah kode lengkap fungsinya. Periksa tautan untuk kemungkinan pembaruan di masa mendatang.

Semoga berhasil.

/**
 * 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
sumber
Terima kasih Mario. Dapatkah Anda mengomentari mengapa Anda memilih ini atas menggunakan $parametersdi menu_build_tree?
Chris Rockwell
Terima kasih untuk umpan baliknya. Saya tidak bisa mendapatkan info yang diperlukan tidak peduli apa yang $parameterssaya gunakan, dan percayalah, saya terlihat banyak. Yang saya inginkan adalah, diberikan jalur, dapatkan semua item menu anak di semua level, dan saya tidak bisa menemukan jalan. Jika ada satu tolong beri tahu saya, saya akan senang untuk belajar dan memperbarui jawaban dan posting blog saya. Bersulang.
Mario Awad