Ajouter par programme un menu de navigation et des éléments de menu

42

Grâce aux fonctions de l’API, je souhaite définir un nouveau menu de navigation , le sélectionner dans le thème actuel, puis insérer quelques pages en tant qu’éléments de menu. Cela doit être fait par exemple sur une activation de thème.

Grâce à un processus (moyennement pénible) de reverse engineering des insertions et des mises à jour de la base de données après avoir configuré manuellement le menu de navigation et les éléments, j'ai regroupé les étapes suivantes, où 'footer-nav' est l'identifiant du slug du menu de navigation I ' m créant:

if (!term_exists('footer-nav', 'nav_menu')) {

    $menu = wp_insert_term('Footer nav', 'nav_menu', array('slug' => 'footer-nav'));

    // Select this menu in the current theme
    update_option('theme_mods_'.get_current_theme(), array("nav_menu_locations" => array("primary" => $menu['term_id'])));

    // Insert new page
    $page = wp_insert_post(array('post_title' => 'Blog',
                                 'post_content' => '',
                                 'post_status' => 'publish',
                                 'post_type' => 'page'));

    // Insert new nav_menu_item
    $nav_item = wp_insert_post(array('post_title' => 'News',
                                     'post_content' => '',
                                     'post_status' => 'publish',
                                     'post_type' => 'nav_menu_item'));


    add_post_meta($nav_item, '_menu_item_type', 'post_type');
    add_post_meta($nav_item, '_menu_item_menu_item_parent', '0');
    add_post_meta($nav_item, '_menu_item_object_id', $page);
    add_post_meta($nav_item, '_menu_item_object', 'page');
    add_post_meta($nav_item, '_menu_item_target', '');
    add_post_meta($nav_item, '_menu_item_classes', 'a:1:{i:0;s:0:"";}');
    add_post_meta($nav_item, '_menu_item_xfn', '');
    add_post_meta($nav_item, '_menu_item_url', '');

    wp_set_object_terms($nav_item, 'footer-nav', 'nav_menu');
}

Cela semble fonctionner, mais:

  • est-ce une manière robuste et élégante de le faire?
  • Me manque-t-il quelque chose de tout à fait évident qui ferait tout cela dans une seule ligne de code?
julien_c
la source

Réponses:

43

Je peux être mal comprendre, mais pourquoi ne pas utiliser wp_create_nav_menu()?

Par exemple, voici ce que je fais pour créer un menu BuddyPress personnalisé lorsque je détecte que BP est actif:

    $menuname = $lblg_themename . ' BuddyPress Menu';
$bpmenulocation = 'lblgbpmenu';
// Does the menu exist already?
$menu_exists = wp_get_nav_menu_object( $menuname );

// If it doesn't exist, let's create it.
if( !$menu_exists){
    $menu_id = wp_create_nav_menu($menuname);

    // Set up default BuddyPress links and add them to the menu.
    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Home'),
        'menu-item-classes' => 'home',
        'menu-item-url' => home_url( '/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Activity'),
        'menu-item-classes' => 'activity',
        'menu-item-url' => home_url( '/activity/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Members'),
        'menu-item-classes' => 'members',
        'menu-item-url' => home_url( '/members/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Groups'),
        'menu-item-classes' => 'groups',
        'menu-item-url' => home_url( '/groups/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Forums'),
        'menu-item-classes' => 'forums',
        'menu-item-url' => home_url( '/forums/' ), 
        'menu-item-status' => 'publish'));

    // Grab the theme locations and assign our newly-created menu
    // to the BuddyPress menu location.
    if( !has_nav_menu( $bpmenulocation ) ){
        $locations = get_theme_mod('nav_menu_locations');
        $locations[$bpmenulocation] = $menu_id;
        set_theme_mod( 'nav_menu_locations', $locations );
    }
ZaMoose
la source
Je ne connaissais pas cette fonction. Oui, j'imagine que le code ci-dessus sera beaucoup plus court. Je suppose que je devrais aller au-delà du Codex et plonger dans le code lui-même, car je trouve que les fonctions de l'API sont souvent, comme dans ce cas, de niveau trop bas. Merci!
julien_c
@julien_c si cela est résolu, marquez-le comme tel pour permettre à ceux qui viendront après vous de profiter de votre expérience ici.
mor7ifer
Je veux juste le tester dans la vraie vie, donc je suis sûr que ça fait ce que je veux. Je me souviendrai de le marquer comme résolu dès que j'aurai terminé!
julien_c
3
Si vous voyez des fonctions utiles comme celles-ci qui ne figurent pas dans le codex, c'est une bonne idée de les ajouter (yay wiki) = p
Tom J Nowell
Désolé, cela m'a pris si longtemps pour vérifier que cela fonctionnait dans mon cas. Réponse acceptée! En outre, vous définissez des éléments de menu de liens personnalisés , j'ai ajouté une réponse ci-dessous pour définir les liens de page (qui seront plus robustes pour les modifications d'URL, par exemple).
julien_c
12

En complément de la réponse de ZaMoose, voici comment créer un élément de menu "Type de page " (et non un élément " Personnalisé "):

wp_update_nav_menu_item($menu_id, 0, array('menu-item-title' => 'About',
                                           'menu-item-object' => 'page',
                                           'menu-item-object-id' => get_page_by_path('about')->ID,
                                           'menu-item-type' => 'post_type',
                                           'menu-item-status' => 'publish'));

En supposant que vous ne connaissiez que le slug de la page, par exemple.

julien_c
la source
9

J'ai quelques problèmes avec la réponse acceptée - cela ne le rend pas faux, mais je posterai mon propre code ci-dessous qui, à mon avis, pourrait donner de meilleurs résultats pour certaines personnes puisque j'avais la même question mais que je voulais faire la même chose. chose avec moins de code.

Premièrement, le code ci-dessus crée des éléments de navigation de type "URL", ce qui convient à certaines personnes, mais je souhaite créer un lien vers PAGES, pas avec des URL, car il s'agit d'une fonctionnalité importante des navigations WordPress. type d'élément de navigation.

De plus, seul un tableau plat d'enfants est traité par le code envoyé. J'ai créé une fonction permettant de déclarer récursivement les nouveaux éléments de navigation, de stocker leurs métadonnées renvoyées (principalement leur identifiant après leur création dans la boucle) et un paramètre permettant d'accepter des enfants.

Il suffit d’éditer $nav_items_to_addet le reste est traité de manière récursive. Il y a 3 clés requises dans chaque tableau. Tout d’abord, la clé de tableau est le slug, donc 'shop' => array( ... )ce que vous voulez pour une page contenant le slug shop. ['title']est la façon dont l'élément de navigation sera étiqueté sur le front-end. pathest le chemin d'accès à la page dans la hiérarchie de la page WordPress, il est donc identique au slug si la page est un parent de niveau supérieur et si elle shopétait un enfant de homece dernier 'path' => 'home/shop'.

La dernière clé facultative est celle ['parent']où vous pouvez déclarer une autre clé du tableau en tant que parent de la clé actuelle. Il est important de noter que les éléments sont ajoutés de manière récursive. Le parent doit donc exister avant de tenter de créer un enfant. Cela signifie que la déclaration doit avoir lieu pour l'élément de navigation parent avant ses enfants.

    $locations = get_nav_menu_locations();

    if (isset($locations['primary_navigation'])) {
        $menu_id = $locations['primary_navigation'];

        $new_menu_obj = array();

        $nav_items_to_add = array(
                'shop' => array(
                    'title' => 'Shop',
                    'path' => 'shop',
                    ),
                'shop_l2' => array(
                    'title' => 'Shop',
                    'path' => 'shop',
                    'parent' => 'shop',
                    ),
                'cart' => array(
                    'title' => 'Cart',
                    'path' => 'shop/cart',
                    'parent' => 'shop',
                    ),
                'checkout' => array(
                    'title' => 'Checkout',
                    'path' => 'shop/checkout',
                    'parent' => 'shop',
                    ),
                'my-account' => array(
                    'title' => 'My Account',
                    'path' => 'shop/my-account',
                    'parent' => 'shop',
                    ),
                'lost-password' => array(
                    'title' => 'Lost Password',
                    'path' => 'shop/my-account/lost-password',
                    'parent' => 'my-account',
                    ),
                'edit-address' => array(
                    'title' => 'Edit My Address',
                    'path' => 'shop/my-account/edit-address',
                    'parent' => 'my-account',
                    ),
            );

    foreach ( $nav_items_to_add as $slug => $nav_item ) {
        $new_menu_obj[$slug] = array();
        if ( array_key_exists( 'parent', $nav_item ) )
            $new_menu_obj[$slug]['parent'] = $nav_item['parent'];
        $new_menu_obj[$slug]['id'] = wp_update_nav_menu_item($menu_id, 0,  array(
                'menu-item-title' => $nav_item['title'],
                'menu-item-object' => 'page',
                'menu-item-parent-id' => $new_menu_obj[ $nav_item['parent'] ]['id'],
                'menu-item-object-id' => get_page_by_path( $nav_item['path'] )->ID,
                'menu-item-type' => 'post_type',
                'menu-item-status' => 'publish')
        );
    }

    }
Brian
la source
2

Pour ajouter un élément de menu par programme. vous pouvez accrocher pour wp_nav_menu_itemsfiltrer. placez le code ci-dessous dans le thème functions.php pour ajouter un élément de menu de connexion / déconnexion dans le menu principal. "Primaire" est le nom / id du menu enregistré.

/**
 * Add login logout menu item in the main menu.
 * ===========================================
 */

add_filter( 'wp_nav_menu_items', 'lunchbox_add_loginout_link', 10, 2 );
function lunchbox_add_loginout_link( $items, $args ) {
    /**
     * If menu primary menu is set & user is logged in.
     */
    if ( is_user_logged_in() && $args->theme_location == 'primary' ) {
        $items .= '<li><a href="'. wp_logout_url() .'">Log Out</a></li>';
    }
    /**
     * Else display login menu item.
     */
    elseif ( !is_user_logged_in() && $args->theme_location == 'primary' ) {
        $items .= '<li><a href="'. site_url('wp-login.php') .'">Log In</a></li>';
    }
    return $items;
}
Aamer Shahzad
la source