Tampilkan sebagian / cabang pohon menu menggunakan wp_nav_menu ()

109

Saya memiliki menu yang didefinisikan dalam WP Admin yang terlihat seperti ini:

teks alternatif

Saya ingin dapat menampilkan semua tautan anak di bilah samping setiap kali saya berada di halaman induk. Misalnya, jika pengguna ada di halaman "Tentang Kami", saya ingin daftar 4 tautan yang disorot berwarna hijau muncul di sidebar.

Saya melihat dokumentasi untuk wp_nav_menu () dan sepertinya tidak memiliki cara bawaan untuk menentukan node tertentu dari menu yang diberikan untuk digunakan sebagai titik awal ketika membuat tautan.

Saya membuat solusi untuk situasi serupa yang mengandalkan hubungan yang dibuat oleh induk laman, tetapi saya mencari solusi yang menggunakan sistem menu secara khusus. Bantuan apa pun akan dihargai.

jessegavin
sumber
2
Jadi Anda ingin mempertahankan seluruh menu sebagai menu khusus, tetapi membuat walker khusus yang menampilkannya hanya memperluas subtree aktif? Suka kode ini , tetapi memperluas wp_nav_menu bukan wp_list_pages? Saya baru-baru ini melakukan sesuatu yang serupa dan dapat memposting kode jika itu yang Anda cari ...
goldenapples
1
@goldenapples, itulah yang saya cari. Jika Anda tidak keberatan memposting kode Anda sebagai jawaban, saya akan sangat berterima kasih.
jessegavin
1
Saya ingin tahu bahwa fungsionalitas yang jelas dan bermanfaat tersebut belum membangunnya. Secara keseluruhan itu sangat berguna untuk situs apa pun yang menggunakan "CMS".
hakre
Saya mencoba menyelesaikan masalah di atas atau yang serupa. Sebagai alternatif saya datang dengan solusi CSS di sini: stackoverflow.com/q/7640837/518169
hyperknot

Jawaban:

75

Ini masih dalam pikiran saya jadi saya meninjau kembali dan mengumpulkan solusi ini, yang tidak terlalu bergantung pada konteks:

add_filter( 'wp_nav_menu_objects', 'submenu_limit', 10, 2 );

function submenu_limit( $items, $args ) {

    if ( empty( $args->submenu ) ) {
        return $items;
    }

    $ids       = wp_filter_object_list( $items, array( 'title' => $args->submenu ), 'and', 'ID' );
    $parent_id = array_pop( $ids );
    $children  = submenu_get_children_ids( $parent_id, $items );

    foreach ( $items as $key => $item ) {

        if ( ! in_array( $item->ID, $children ) ) {
            unset( $items[$key] );
        }
    }

    return $items;
}

function submenu_get_children_ids( $id, $items ) {

    $ids = wp_filter_object_list( $items, array( 'menu_item_parent' => $id ), 'and', 'ID' );

    foreach ( $ids as $id ) {

        $ids = array_merge( $ids, submenu_get_children_ids( $id, $items ) );
    }

    return $ids;
}

Pemakaian

$args = array(
    'theme_location' => 'slug-of-the-menu', // the one used on register_nav_menus
    'submenu' => 'About Us', // could be used __() for translations
);

wp_nav_menu( $args );
Jarang
sumber
Teknik yang indah! Bolehkah saya bertanya sesuatu yang mungkin berkaitan dengan yang ini: Bagaimana Anda menampilkan konten dari halaman submenu yang tercantum dalam template?
daniel.tosaba
2
@ daniel.tosaba Anda harus membuat subkelas atau menggunakan filter di Walker_Nav_Menukelas. Suka semua menu terlalu banyak untuk dikomentari - ajukan pertanyaan baru tentang itu?
Rarst
3
Jawaban yang sangat fantastis. Terima kasih banyak. Ini harus benar-benar menjadi opsi default di WordPress.
Dotty
3
Sangat rapi. Jika ada yang tertarik, untuk melakukan hal yang sama tetapi dengan ID halaman, ubah wp_filter_object_listbaris kewp_filter_object_list( $items, array( 'object_id' => $args->submenu ), 'and', 'ID' );
Ben
14

@goldenapples: Kelas Walker Anda tidak berfungsi. Tapi idenya benar-benar bagus. Saya membuat alat bantu jalan berdasarkan ide Anda:

class Selective_Walker extends Walker_Nav_Menu
{
    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output = '';

        if ($max_depth < -1) //invalid parameter
            return $output;

        if (empty($elements)) //nothing to walk
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // flat display
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * need to display in hierarchical order
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        /*
         * when none of the elements is top level
         * assume the first one must be root of the sub elements
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  //added by continent7
        foreach ( $top_level_elements as $e ){  //changed by continent7
            // descend only on current tree
            $descend_test = array_intersect( $current_element_markers, $e->classes );
            if ( !empty( $descend_test ) ) 
                $this->display_element( $e, $children_elements, 2, 0, $args, $output );
        }

        /*
         * if we are displaying all levels, and remaining children_elements is not empty,
         * then we got orphans, which should be displayed regardless
         */
         /* removed by continent7
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }
        */
         return $output;
    }
}

Sekarang Anda dapat menggunakan:

<?php wp_nav_menu( 
   array(
       'theme_location'=>'test', 
       'walker'=>new Selective_Walker() ) 
   ); ?>

Outputnya adalah daftar yang mengandung elemen root saat ini dan itu anak-anak (bukan anak-anak mereka). Def: Root element: = Item menu tingkat atas yang sesuai dengan halaman saat ini atau merupakan induk dari halaman saat ini atau induk dari induk ...

Ini tidak persis menjawab pertanyaan asli tetapi hampir, karena masih ada item tingkat atas. Ini baik untuk saya, karena saya ingin elemen tingkat atas sebagai judul sidebar. Jika Anda ingin menghilangkan ini, Anda mungkin harus mengganti display_element atau menggunakan HTML-Parser.

davidn
sumber
12

Hai @jessegavin :

Nav Menu disimpan dalam kombinasi jenis kiriman khusus dan taksonomi khusus. Setiap menu disimpan sebagai Istilah (yaitu "Tentang Menu" , ditemukan di wp_terms) dari Taksonomi Kustom (yaitu nav_menu, ditemukan di wp_term_taxonomy.)

Setiap Item Menu Nav disimpan sebagai pos post_type=='nav_menu_item'(yaitu "Tentang Firma" , ditemukan di wp_posts) dengan atributnya yang disimpan sebagai pos meta (in wp_postmeta) menggunakan meta_keyawalan di _menu_item_*mana _menu_item_menu_item_parentID induk item item item menu Nav Menu Anda.

Hubungan antara menu dan item menu disimpan di wp_term_relationshipstempat yang object_idberkaitan dengan $post->IDuntuk Item Menu Nav dan yang $term_relationships->term_taxonomy_idterkait dengan menu yang ditentukan secara kolektif dalam wp_term_taxonomydan wp_terms.

Saya cukup yakin akan memungkinkan untuk menghubungkan keduanya 'wp_update_nav_menu'dan 'wp_update_nav_menu_item'untuk membuat menu yang sebenarnya di dalam wp_termsdan serangkaian hubungan paralel wp_term_taxonomydan di wp_term_relationshipsmana setiap Item Menu Nav yang memiliki item Menu sub-Nav juga menjadi Menu Nav itu sendiri.

Anda juga ingin mengait 'wp_get_nav_menus' (yang saya sarankan ditambahkan ke WP 3.0 berdasarkan beberapa pekerjaan serupa yang saya lakukan beberapa bulan yang lalu) untuk memastikan bahwa Nav Menu yang Anda buat tidak ditampilkan untuk manipulasi oleh pengguna di admin, jika tidak mereka akan akan keluar dari sinkronisasi dengan sangat cepat dan kemudian Anda akan memiliki mimpi buruk data di tangan Anda.

Kedengarannya seperti proyek yang menyenangkan dan bermanfaat, tetapi ini sedikit lebih banyak kode dan pengujian daripada yang bisa saya tangani saat ini sebagian karena segala sesuatu yang menyinkronkan data cenderung menjadi PITA ketika harus menyelesaikan semua bug (dan karena klien yang membayar mendesak saya untuk menyelesaikan sesuatu. :) Tapi dengan informasi di atas, saya cukup termotivasi pengembang plugin WordPress dapat mengkodekannya jika mereka mau.

Tentu saja Anda menyadari sekarang jika Anda melakukan kode itu Anda berkewajiban untuk mempostingnya kembali di sini sehingga kita semua dapat memperoleh manfaat dari sumbangan Anda! :-)

MikeSchinkel
sumber
Saya tidak yakin bahwa saya mengikuti apa yang Anda katakan. Saya mencari solusi read-only untuk menampilkan "sub-menu" yang terkait dengan halaman saat ini di pengguna. Apakah kita membicarakan hal yang sama? - Saya sangat menghargai penjelasan Anda yang lebih dalam tentang skema basis data.
jessegavin
@jessegavin - Ya, jika Anda ingin menelepon wp_nav_menu()maka Anda harus mengkloning menu karena tergabung wp_nav_menu()erat dengan struktur menu . Pilihan lainnya adalah menyalin wp_nav_menu()kode dan membuat modifikasi yang diperlukan untuk ditampilkan sebagai submenu.
MikeSchinkel
10

Ini adalah ekstensi alat bantu yang harus melakukan apa yang Anda cari:

class Selective_Walker extends Walker_Nav_Menu
{

    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output = '';

        if ($max_depth < -1) //invalid parameter
            return $output;

        if (empty($elements)) //nothing to walk
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // flat display
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * need to display in hierarchical order
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        /*
         * when none of the elements is top level
         * assume the first one must be root of the sub elements
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );

        foreach ( $top_level_elements as $e ) {

            // descend only on current tree
            $descend_test = array_intersect( $current_element_markers, $e->classes );
            if ( empty( $descend_test ) )  unset ( $children_elements );

            $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
        }

        /*
         * if we are displaying all levels, and remaining children_elements is not empty,
         * then we got orphans, which should be displayed regardless
         */
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }

         return $output;
    }

}

Berdasarkan longgar pada kode mfields, saya merujuk pada komentar saya sebelumnya. Yang perlu dilakukan hanyalah memeriksa saat menjalankan menu untuk melihat apakah elemen saat ini adalah (1) item menu saat ini, atau (2) leluhur dari item menu saat ini, dan perluas subtree di bawahnya hanya jika salah satu dari kondisi tersebut benar . Semoga ini berhasil untuk Anda.

Untuk menggunakannya, cukup tambahkan argumen "walker" ketika Anda memanggil menu, yaitu:

<?php wp_nav_menu( 
   array(
       'theme_location'=>'test', 
       'walker'=>new Selective_Walker() ) 
   ); ?>
lempengan emas
sumber
Oh ... Saya baru saja membaca kembali pertanyaan Anda dan menyadari bahwa saya telah salah paham pada awalnya. Walker ini akan menampilkan semua item menu tingkat atas lainnya, hanya saja tidak perlu diperluas. Ini bukan apa yang ingin Anda lakukan. Namun, kode ini dapat dimodifikasi dengan cara apa pun yang Anda inginkan. Lihat saja loop through $top_level_elementsdan tambahkan tes Anda sendiri sebelum panggilan $this->display_element.
goldenappples
Apakah mungkin untuk mendapatkan kelas ini untuk menunjukkan kedalaman subhalaman saat ini? Yaitu .. Jika saya memiliki kedalaman tiga level atau lebih, apakah level ketiga dan selanjutnya ditampilkan untuk halaman (sub) saat ini? Saat ini, hanya menunjukkan A> B, dan bukan> C (C menjadi yang ketiga (level)
Zolomon
@ Zolomon - Saya tidak yakin saya mengerti pertanyaan Anda. Ini harus memperluas seluruh pohon di bawah setiap item menu dengan kelas 'menu-menu-item', 'menu-induk-saat ini', atau 'leluhur menu-saat'. Ketika saya mengujinya, ini akan menampilkan semua tingkat subhalaman dalam menu. Apa yang ingin Anda lakukan?
goldenples
Mungkin Anda ingin meneruskan depthparameter ke panggilan wp_nav_menu, jika tema Anda entah bagaimana mengungguli default 0 (tampilkan semua level)?
goldenappples
8

Pembaruan: Saya menjadikan ini sebagai plugin. Unduh di sini .


Saya perlu menyelesaikan ini sendiri dan akhirnya menulis filter pada hasil pencarian menu. Ini memungkinkan Anda menggunakan wp_nav_menuseperti biasa, tetapi memilih sub-bagian menu berdasarkan judul elemen induk. Tambahkan submenuparameter ke menu seperti ini:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => 'About Us',
));

Anda bahkan dapat masuk ke beberapa level dengan memasukkan garis miring:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => 'About Us/Board of Directors'
));

Atau jika Anda lebih suka dengan array:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => array('About Us', 'Board of Directors')
));

Ini menggunakan versi slug dari judul, yang harus membuatnya memaafkan hal-hal seperti huruf besar dan tanda baca.

Marcus Downing
sumber
Apakah mungkin menjangkau submenu melalui id? Maksud saya id halaman, atau posting id.
Digerkam
split () sudah usang, ganti $loc = split( "/", $loc );dalam plugin dengan$loc = preg_split( "~/~", $loc );
Floris
Saya juga menyarankan untuk membuat $ submenu opsional. Jadi Anda masih bisa mengambil seluruh menu saat dibutuhkan. Tambahkan ini ke filter ke atas: `if (! Isset ($ args-> submenu)) {return $ items; } `
Floris
8

Saya mengumpulkan kelas berikut untuk diri saya sendiri. Ini akan menemukan orang tua nav atas halaman saat ini, atau Anda dapat memberikannya ID nav atas target di konstruktor walker.

class Walker_SubNav_Menu extends Walker_Nav_Menu {
    var $target_id = false;

    function __construct($target_id = false) {
        $this->target_id = $target_id;
    }

    function walk($items, $depth) {
        $args = array_slice(func_get_args(), 2);
        $args = $args[0];
        $parent_field = $this->db_fields['parent'];
        $target_id = $this->target_id;
        $filtered_items = array();

        // if the parent is not set, set it based on the post
        if (!$target_id) {
            global $post;
            foreach ($items as $item) {
                if ($item->object_id == $post->ID) {
                    $target_id = $item->ID;
                }
            }
        }

        // if there isn't a parent, do a regular menu
        if (!$target_id) return parent::walk($items, $depth, $args);

        // get the top nav item
        $target_id = $this->top_level_id($items, $target_id);

        // only include items under the parent
        foreach ($items as $item) {
            if (!$item->$parent_field) continue;

            $item_id = $this->top_level_id($items, $item->ID);

            if ($item_id == $target_id) {
                $filtered_items[] = $item;
            }
        }

        return parent::walk($filtered_items, $depth, $args);
    }

    // gets the top level ID for an item ID
    function top_level_id($items, $item_id) {
        $parent_field = $this->db_fields['parent'];

        $parents = array();
        foreach ($items as $item) {
            if ($item->$parent_field) {
                $parents[$item->ID] = $item->$parent_field;
            }
        }

        // find the top level item
        while (array_key_exists($item_id, $parents)) {
            $item_id = $parents[$item_id];
        }

        return $item_id;
    }
}

Panggilan Nav:

wp_nav_menu(array(
    'theme_location' => 'main_menu',
    'walker' => new Walker_SubNav_Menu(22), // with ID
));
Mat
sumber
4

@davidn @hakre Hai, saya punya solusi jelek tanpa HTML-Parser atau override display_element.

 class Selective_Walker extends Walker_Nav_Menu
    {
        function walk( $elements, $max_depth) {

            $args = array_slice(func_get_args(), 2);
            $output = '';

            if ($max_depth < -1) //invalid parameter
                return $output;

            if (empty($elements)) //nothing to walk
                return $output;

            $id_field = $this->db_fields['id'];
            $parent_field = $this->db_fields['parent'];

            // flat display
            if ( -1 == $max_depth ) {
                $empty_array = array();
                foreach ( $elements as $e )
                    $this->display_element( $e, $empty_array, 1, 0, $args, $output );
                return $output;
            }

            /*
             * need to display in hierarchical order
             * separate elements into two buckets: top level and children elements
             * children_elements is two dimensional array, eg.
             * children_elements[10][] contains all sub-elements whose parent is 10.
             */
            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( 0 == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }

            /*
             * when none of the elements is top level
             * assume the first one must be root of the sub elements
             */
            if ( empty($top_level_elements) ) {

                $first = array_slice( $elements, 0, 1 );
                $root = $first[0];

                $top_level_elements = array();
                $children_elements  = array();
                foreach ( $elements as $e) {
                    if ( $root->$parent_field == $e->$parent_field )
                        $top_level_elements[] = $e;
                    else
                        $children_elements[ $e->$parent_field ][] = $e;
                }
            }

            $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  //added by continent7
            foreach ( $top_level_elements as $e ){  //changed by continent7
                // descend only on current tree
                $descend_test = array_intersect( $current_element_markers, $e->classes );
                if ( !empty( $descend_test ) ) 
                    $this->display_element( $e, $children_elements, 2, 0, $args, $output );
            }

            /*
             * if we are displaying all levels, and remaining children_elements is not empty,
             * then we got orphans, which should be displayed regardless
             */
             /* removed by continent7
            if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
                $empty_array = array();
                foreach ( $children_elements as $orphans )
                    foreach( $orphans as $op )
                        $this->display_element( $op, $empty_array, 1, 0, $args, $output );
             }
            */

/*added by alpguneysel  */
                $pos = strpos($output, '<a');
            $pos2 = strpos($output, 'a>');
            $topper= substr($output, 0, $pos).substr($output, $pos2+2);
            $pos3 = strpos($topper, '>');
            $lasst=substr($topper, $pos3+1);
            $submenu= substr($lasst, 0, -6);

        return $submenu;
        }
    }
Alp Güneysel
sumber
Setelah mencoba semuanya, solusi Alp adalah satu-satunya yang bekerja untuk saya. Namun satu masalah dengan itu. Itu hanya menunjukkan anak-anak tingkat pertama, tetapi tidak menunjukkan anak-anak tingkat ketiga atau keempat. Saya sudah berusaha selama berhari-hari untuk mendapatkannya. Adakah yang tahu cara memodifikasi solusinya? PS. Itu tidak akan membiarkan saya menambahkan komentar sehingga perlu melakukannya sebagai jawaban.
cchiera
3

Output menu nav mencakup banyak kelas untuk item saat ini, leluhur item saat ini, dll. Dalam beberapa situasi, saya telah dapat melakukan apa yang ingin Anda lakukan dengan membiarkan seluruh output nav tree, dan kemudian menggunakan css untuk menguraikannya ke hanya anak-anak dari halaman saat ini, dll.


sumber
3

Saya membuat alat bantu jalan yang dimodifikasi yang akan membantu! Tidak sempurna - ia meninggalkan beberapa elemen kosong, tetapi ia berhasil. Modifikasi pada dasarnya adalah bit $ current_branch tersebut. Semoga ini bisa membantu seseorang!

class Kanec_Walker_Nav_Menu extends Walker {
/**
 * @see Walker::$tree_type
 * @since 3.0.0
 * @var string
 */
var $tree_type = array( 'post_type', 'taxonomy', 'custom' );

/**
 * @see Walker::$db_fields
 * @since 3.0.0
 * @todo Decouple this.
 * @var array
 */
var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );

/**
 * @see Walker::start_lvl()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param int $depth Depth of page. Used for padding.
 */
function start_lvl(&$output, $depth) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n$indent<ul class=\"sub-menu\">\n";
}

/**
 * @see Walker::end_lvl()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param int $depth Depth of page. Used for padding.
 */
function end_lvl(&$output, $depth) {
    global $current_branch;
    if ($depth == 0) $current_branch = false;
    $indent = str_repeat("\t", $depth);
    $output .= "$indent</ul>\n";
}

/**
 * @see Walker::start_el()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param object $item Menu item data object.
 * @param int $depth Depth of menu item. Used for padding.
 * @param int $current_page Menu item ID.
 * @param object $args
 */
function start_el(&$output, $item, $depth, $args) {
    global $wp_query;
    global $current_branch;

    // Is this menu item in the current branch?
    if(in_array('current-menu-ancestor',$item->classes) ||
    in_array('current-menu-parent',$item->classes) ||
    in_array('current-menu-item',$item->classes)) {
        $current_branch = true; 
    }

    if($current_branch && $depth > 0) {
        $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

        $class_names = $value = '';

        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;

        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
        $class_names = ' class="' . esc_attr( $class_names ) . '"';

        $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
        $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

        $output .= $indent . '<li' . $id . $value . $class_names .'>';

        $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
        $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
        $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
        $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

        $item_output = $args->before;
        $item_output .= '<a'. $attributes .'>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;

        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }

}

/**
 * @see Walker::end_el()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param object $item Page data object. Not used.
 * @param int $depth Depth of page. Not Used.
 */
function end_el(&$output, $item, $depth) {
    global $current_branch;
    if($current_branch && $depth > 0) $output .= "</li>\n";
    if($depth == 0) $current_branch = 0;
}

}


sumber
3

Lihat kode di plugin saya atau gunakan untuk tujuan Anda;)

Plugin ini menambahkan widget "Navigasi Menu" yang disempurnakan. Ini menawarkan banyak opsi yang dapat diatur untuk menyesuaikan output dari menu kustom melalui widget.

Fitur termasuk:

  • Hirarki khusus - "Hanya sub-item yang terkait" atau "Hanya sub-item yang benar-benar terkait".
  • Mulai kedalaman dan level maksimum untuk menampilkan + tampilan datar.
  • Tampilkan semua item menu mulai dari yang dipilih.
  • Tampilkan hanya jalur langsung ke elemen saat ini atau hanya anak-anak dari
    item yang dipilih (opsi untuk memasukkan item induk).
  • Kelas khusus untuk blok widget.
  • Dan hampir semua parameter untuk fungsi wp_nav_menu.

http://wordpress.org/extend/plugins/advanced-menu-widget/

Ján Bočínec
sumber