Deskripsi item menu? Custom Walker untuk wp_nav_menu ()

104

Menu Wordpress Normal terlihat seperti:

Beranda | Blog | Tentang kami | Kontak

Tetapi saya telah melihat banyak halaman dengan deskripsi di bawah tautan ini:

Halaman Depan | Blog Kami | Tentang kami | Kontak
.... temui kami ... | baca lebih lanjut | info dasar | formulir kontak

Bagaimana cara mencapai ini?

(Saya ingin ini menjadi fungsi inti untuk semua tema saya, jadi jangan plugin, saya hanya ingin tahu bagaimana caranya)

Wordpressor
sumber

Jawaban:

115

Anda memerlukan walker khusus untuk menu nav.

Pada dasarnya, Anda menambahkan parameter 'walker'ke wp_nav_menu()opsi dan memanggil instance kelas yang ditingkatkan:

wp_nav_menu(
    array (
        'menu'            => 'main-menu',
        'container'       => FALSE,
        'container_id'    => FALSE,
        'menu_class'      => '',
        'menu_id'         => FALSE,
        'depth'           => 1,
        'walker'          => new Description_Walker
    )
);

Kelas Description_Walkermemperluas Walker_Nav_Menudan mengubah fungsi yang start_el( &$output, $item, $depth, $args )dicari $item->description.

Contoh dasar:

/**
 * Create HTML list of nav menu items.
 * Replacement for the native Walker, using the description.
 *
 * @see    https://wordpress.stackexchange.com/q/14037/
 * @author fuxia
 */
class Description_Walker extends Walker_Nav_Menu
{
    /**
     * Start the element output.
     *
     * @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. May be used for padding.
     * @param  array|object $args    Additional strings. Actually always an 
                                     instance of stdClass. But this is WordPress.
     * @return void
     */
    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
    {
        $classes     = empty ( $item->classes ) ? array () : (array) $item->classes;

        $class_names = join(
            ' '
        ,   apply_filters(
                'nav_menu_css_class'
            ,   array_filter( $classes ), $item
            )
        );

        ! empty ( $class_names )
            and $class_names = ' class="'. esc_attr( $class_names ) . '"';

        $output .= "<li id='menu-item-$item->ID' $class_names>";

        $attributes  = '';

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

        // insert description for top level elements only
        // you may change this
        $description = ( ! empty ( $item->description ) and 0 == $depth )
            ? '<small class="nav_desc">' . esc_attr( $item->description ) . '</small>' : '';

        $title = apply_filters( 'the_title', $item->title, $item->ID );

        $item_output = $args->before
            . "<a $attributes>"
            . $args->link_before
            . $title
            . '</a> '
            . $args->link_after
            . $description
            . $args->after;

        // Since $output is called by reference we don't need to return anything.
        $output .= apply_filters(
            'walker_nav_menu_start_el'
        ,   $item_output
        ,   $item
        ,   $depth
        ,   $args
        );
    }
}

Atau, sebagai alternatif seperti yang dikomentari @nevvermind , Anda bisa mewarisi semua fungsi dari fungsi induk start_eldan hanya menambahkan deskripsi ke $output:

function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) 
{
    parent::start_el( $output, $item, $depth, $args );
    $output .= sprintf( 
        '<i>%s</i>', 
        esc_html( $item->description ) 
    );
}

Output sampel:

masukkan deskripsi gambar di sini

Sekarang aktifkan bidang deskripsi wp-admin/nav-menus.phpuntuk mendapatkan kemampuan mengedit bidang ini. Jika Anda tidak, WP hanya membuang konten posting lengkap Anda ke dalamnya.

masukkan deskripsi gambar di sini

Bacaan lebih lanjut:

Dan itu saja.

fuxia
sumber
11
Jika untuk Anda warisan! = Tulis ulang seluruh metode , gunakan nama yang sama , coba ini:public function start_el(&$output, $item, $depth, $args) { parent::start_el($output, $item, $depth, $args); $output .= sprintf('<i>%s</i>', esc_html($item->description)); }
nevvermind
2
@nevvermind Anda setidaknya harus memeriksa apakah deskripsi tersebut memiliki beberapa konten. ;) Posisi uraian dalam kode sampel saya hanyalah cara paling sederhana untuk menggambarkan solusinya. Jika Anda perlu memasukkan deskripsi ke jangkar, Anda harus membangun kembali seluruh fungsi.
fuxia
1
ya, Anda harus menulis seluruh metode, tidak diragukan lagi, tetapi bagi orang-orang yang perlu (katakanlah ...) menambahkannya, itu mungkin hanya menyelamatkan mereka dari banyak sakit kepala. Dan ini semua salah WP. Arrrgh!
nevvermind
Bagus dan saya sudah menggunakannya dalam jawaban ini dengan memodifikasi sedikit, mungkin Anda bisa membuatnya lebih baik jika saya melewatkan sesuatu, terima kasih.
The Alpha
Apa yang saya benar-benar diperlukan adalah yang wp_nav_menu , tapi saya perlu untuk mengubah parameter 'container_class', bekerja untuk kasus penggunaan tertentu saya, di mana saya pada beberapa kondisi bertukar menu utama untuk satu sama lain, tetapi diperlukan kelas untuk konsisten untuk css.
D. Dan
33

Sejak WordPress 3.0 , Anda tidak memerlukan walker khusus lagi!

Ada walker_nav_menu_start_elfilternya, lihat https://developer.wordpress.org/reference/hooks/walker_nav_menu_start_el/

Contoh:

function add_description_to_menu($item_output, $item, $depth, $args) {
    if (strlen($item->description) > 0 ) {
        // append description after link
        $item_output .= sprintf('<span class="description">%s</span>', esc_html($item->description));

        // insert description as last item *in* link ($input_output ends with "</a>{$args->after}")
        //$item_output = substr($item_output, 0, -strlen("</a>{$args->after}")) . sprintf('<span class="description">%s</span >', esc_html($item->description)) . "</a>{$args->after}";
    }

    return $item_output;
}
add_filter('walker_nav_menu_start_el', 'add_description_to_menu', 10, 4);
Joost
sumber
1
Bagus! Saya menggunakan solusi nav walker oleh @toscho, tapi ini jauh lebih bersih dan lebih mudah untuk dipelihara. Ini harus menjadi jawaban yang diterima, latihan yang jauh lebih baik.
Neejoh
8

Ini tidak lebih baik atau lebih buruk daripada saran lainnya; hanya berbeda. Ini pendek dan manis juga.

Daripada menggunakan bidang deskripsi seperti yang disarankan @toscho , Anda bisa mengisi bidang "Judul" pada setiap item menu dengan teks yang Anda inginkan, dan kemudian menggunakan CSS ini:

.menu-item a:after { content: attr(title); }

Ini juga akan mudah untuk menggunakan jQuery untuk menambahkannya, tetapi teksnya cukup hias sehingga CSS tampaknya tepat.

mrwweb
sumber
2

Anda juga dapat menulis <span>elemen setelah label navigasi di menu dan menggunakan aturan CSS berikut untuk mengubah displaypengaturannya (secara inlinedefault):

span {display:block}
Markus
sumber
2
Yah itu solusi yang sederhana dan mudah tetapi mengapa menggunakan spanjika Anda membuatnya tetap? xhtml / html4 tidak memungkinkan elemen blok di dalam tautan, html5 namun demikian, jadi gunakan saja div, dan tidak perlu untuk css!
James Mitch