How to customize wordpress menus

const defaultMenu = ['borscht', 'rye bread']

const muchBetterMenu = menuCustomizer(defaultMenu, [species, sauces])

function menuCustomizer(menu, supplements) {
    return menu.map(item => addIngedient(item, supplements))
}

This is a tutorial on how to enchance a wordpress menu with posts thumbnails. Assuming you are aware of using child themes and theirs functions.php. All the code provided here is used in this functions.php

We are creating a child of Walker class, which is used for "displaying various tree-like structures", this way:


class Walker_Thumbnail_Menu extends Walker {
    // Tell Walker where to inherit it's parent and id values
    var $db_fields = array(
        'parent' => 'menu_item_parent',
        'id'     => 'db_id'
    );
    // menu item builder function
    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
        $cat_ids = wp_get_post_categories($item->object_id);
        $cat_object = (object) [
            'url' => get_category_link( $cat_ids[0] ),
            'name' => get_cat_name( $cat_ids[0] ),
        ];
        $category = sprintf(
            "<div class='category'><a href='%s'>%s</a></div>",
            $cat_object->url,
            $cat_object->name
        );
        $thumb = sprintf( "<div class='thumbnail'><a href='%s'&tg;%s</a></div>",
            $item->url,
            get_the_post_thumbnail( $item->object_id, 'thumbnail' )
        );
        $output .= sprintf( "\n<li class='menu-item'>%s<div class='post'><a class='post-link' href='%s'>%s</a>%s</div></li>\n",
            $thumb,
            $item->url,
            $item->title,
            $category
        );
    }
}

Edit the builder function to produce html you need.

Now check a name of the menu you are enchancing. We are using it in custom walker instance:


function menu_thumbs($menu, $args) {
    // put here the menu name
    if ($args->menu->name !== 'Menu name')
        return $menu;

    $output = wp_nav_menu(array(
        'menu'       => $args->menu->name, // menu id
        'menu_class' => 'thumbnailed_menu',
        'walker'     => new Walker_Thumbnail_Menu() // use our custom walker
    ));

    return $output;
}

And now execute it:


add_filter( 'wp_nav_menu_items', 'menu_thumbs', 10, 2 );

Apply some css and enjoy the result:

thumbnailed menu items

Possible trap: it's not really good to use the menu name in code. At some moment content editor may decide to rename it and your thumbnails will be lost at this point:


if ($args->menu->name !== 'Menu name')
    return $menu;

So the editor should be aware of this and update the code...

The plan is to make some flag in menu settings.