Programmgesteuertes Hinzufügen eines Navigationsmenüs und von Menüelementen

41

Über API-Funktionen möchte ich ein neues Navigationsmenü definieren , es im aktuellen Thema auswählen und dann einige Seiten als Menüelemente einfügen. Dies soll zum Beispiel bei einer Themenaktivierung geschehen.

Durch einen (mäßig schmerzhaften) Prozess des Reverse Engineerings, bei dem die Datenbank nach dem manuellen Einrichten des Navigationsmenüs und der Elemente eingefügt und aktualisiert wird, habe ich die folgenden Schritte zusammengesetzt, wobei 'footer-nav' die Slug-ID des Navigationsmenüs I 'ist. Ich erstelle:

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

Dies scheint zu funktionieren, aber:

  • ist es eine robuste und elegante Art, es zu tun?
  • Fehlt mir etwas völlig offensichtliches, das all dies in einer Codezeile tun würde?
julien_c
quelle

Antworten:

42

Ich könnte Sie missverstehen, aber warum nicht benutzen wp_create_nav_menu()?

ZB ist dies, was ich mache, um ein benutzerdefiniertes BuddyPress-Menü zu erstellen, wenn ich BP als aktiv erkenne:

    $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
quelle
Ich wusste nichts über diese Funktion. Ja, ich denke, es wird den obigen Code viel kürzer machen. Ich denke, ich sollte über den Codex hinausgehen und in den eigentlichen Code eintauchen, da ich finde, dass die API-Funktionen oft zu niedrig sind, wie in diesem Fall. Vielen Dank!
Julien_C
@julien_c Wenn dies behoben ist, markieren Sie es als solches, damit diejenigen, die nach Ihnen kommen, von Ihren Erfahrungen hier profitieren können.
Mor7ifer
Ich möchte es einfach nur im wirklichen Leben testen, also bin ich mir sicher, dass es das tut, was ich will. Ich werde daran denken, es als gelöst zu markieren, sobald ich fertig bin!
Julien_C
3
Wenn Sie nützliche Funktionen wie diese sehen, die nicht im Codex enthalten sind, ist es eine gute Idee, sie hinzuzufügen (yay wiki) = p
Tom J Nowell
Es tut mir leid, dass ich so lange gebraucht habe, um zu überprüfen, ob es in meinem Fall funktioniert hat. Antwort akzeptiert! Außerdem definieren Sie benutzerdefinierte Link- Menüelemente. Ich habe unten eine Antwort hinzugefügt, um Seitenlinks zu definieren (die beispielsweise für URL-Änderungen robuster sind).
julien_c
12

Als Ergänzung zu zamoose des anwser, hier ist, wie man einen „würde erstellen Seiten vom Typ“ Menüpunkt (keine „ Benutzerdefiniert “ einen):

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'));

Angenommen, Sie kennen nur den Page Slug.

julien_c
quelle
9

Ich habe ein paar Probleme mit der akzeptierten Antwort - das macht es nicht falsch, aber ich werde meinen eigenen Code posten, unter dem ich glaube, dass einige Leute ein besseres Ergebnis erzielen, da ich die gleiche Frage hatte, aber das gleiche tun wollte etwas mit weniger Code.

Erstens erzeugt der obige Code Navigationselemente vom Typ "URL", was für einige Leute in Ordnung ist, aber ich möchte auf SEITEN verlinken, nicht auf URLs, da dies ein wichtiges Merkmal von WordPress-Navigationen ist und Clients unvermeidlich Dinge verschieben, so dass ich die URL niemals verwende Navigationselementtyp.

Außerdem wird nur ein flaches Array von untergeordneten Elementen von der Postleitzahl verarbeitet. Ich habe eine Funktion zum rekursiven Deklarieren der neuen Navigationselemente, Speichern der zurückgegebenen Metadaten (hauptsächlich der ID nach dem Erstellen in der Schleife) und einen Parameter zum Akzeptieren von untergeordneten Elementen erstellt.

Einfach bearbeiten $nav_items_to_addund der Rest wird rekursiv behandelt. In jedem Array sind 3 Schlüssel erforderlich. Erstens ist der Array-Schlüssel der Slug, also 'shop' => array( ... )das, was Sie für eine Seite mit dem Slug wollen shop. ['title']ist die Art und Weise, wie das Navigationselement am vorderen Ende beschriftet wird. pathist der Pfad zu der Seite innerhalb der WordPress-Seitenhierarchie. Dies ist also identisch mit dem Slug, wenn die Seite ein übergeordnetes Element auf oberster Ebene ist und shopein untergeordnetes homeElement wäre 'path' => 'home/shop'.

Mit dem letzten optionalen Array-Schlüssel ['parent']können Sie einen anderen Schlüssel im Array als übergeordneten Schlüssel des aktuellen deklarieren. Es ist wichtig zu beachten, dass die Elemente rekursiv hinzugefügt werden, sodass das übergeordnete Element vorhanden sein muss, bevor Sie versuchen, ein untergeordnetes Element zu erstellen. Dies bedeutet, dass die Deklaration für das übergeordnete Navigationselement erfolgen sollte, bevor es untergeordnet ist.

    $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
quelle
2

So fügen Sie programmgesteuert einen Menüpunkt hinzu Sie können einhaken, um zu wp_nav_menu_itemsfiltern. Platzieren Sie den folgenden Code in der Datei functions.php, um den Menüpunkt Anmelden / Abmelden im Hauptmenü hinzuzufügen. 'Primär' ist der Name / die ID des registrierten Menüs.

/**
 * 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
quelle