Agregar programáticamente un menú de navegación y elementos de menú

37

A través de las funciones de la API, quiero definir un nuevo Menú de navegación , seleccionarlo en el tema actual y luego insertar algunos Páginas como elementos de menú. Esto se debe hacer, por ejemplo, en la activación de un tema.

A través de un proceso (moderadamente doloroso) de ingeniería inversa, la base de datos se inserta y se actualiza después de configurar manualmente el menú y los elementos de navegación. He reunido los siguientes pasos, donde 'footer-nav' es el ID de barra de navegación menú estoy creando:

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

Esto parece funcionar, pero:

  • ¿Es una forma robusta y elegante de hacerlo?
  • ¿me estoy perdiendo algo totalmente obvio que haría todo esto en una línea de código?
pregunta julien_c 07.03.2012 - 14:43

4 respuestas

39

Puede que te esté entendiendo mal, pero ¿por qué no usar wp_create_nav_menu() ?

Por ejemplo, esto es lo que hago para crear un menú personalizado de BuddyPress cuando detecto BP como activo:

    $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 );
    }
    
respondido por el ZaMoose 07.03.2012 - 15:03
12

Como complemento a la herramienta de respuesta de ZaMoose, a continuación se explica cómo crearía un elemento de menú " Página -tipo" (no uno " Personalizado "):

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

Suponiendo que solo conoce la barra de página, por ejemplo.

    
respondido por el julien_c 15.05.2012 - 13:04
9

Tengo algunos problemas con la respuesta aceptada, eso no lo hace incorrecto, pero publicaré mi propio código debajo del cual creo que podría tener un mejor resultado para algunas personas ya que tenía la misma pregunta pero quería haga lo mismo con menos código.

Primero, el código anterior crea elementos de navegación de tipo "URL", lo cual está bien para algunas personas, pero quiero enlazar a PÁGINAS, no a URL porque esta es una característica importante de las navegaciones de WordPress y los clientes inevitablemente mueven las cosas para que nunca utilizar el tipo de elemento de navegación URL.

Además, el código publicado solo maneja una gran cantidad de hijos. He creado una función para declarar recursivamente los nuevos elementos de navegación, almacenar sus metadatos devueltos (principalmente ID después de crearlos en el bucle) y un parámetro para aceptar hijos.

Solo edite $nav_items_to_add y el resto se manejará recursivamente. Hay 3 claves requeridas en cada matriz. Primero, la clave de la matriz es el slug, por lo que 'shop' => array( ... ) es lo que desea para una página con el slug shop . ['title'] es la forma en que se etiquetará el elemento de navegación en el extremo delantero. path es la ruta a la página dentro de la jerarquía de páginas de WordPress, por lo que es idéntica a la barra si la página es un padre de nivel superior, y si shop fuera un hijo de home , entonces sería 'path' => 'home/shop' .

La última clave de matriz opcional es ['parent'] , donde puede declarar otra clave en la matriz como la principal de la actual. Es importante tener en cuenta que los elementos se agregan de forma recursiva, por lo que el padre debe existir antes de intentar crear un hijo. Esto significa que la declaración debe ocurrir para el elemento de navegación principal antes de que sea secundaria.

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

    }
    
respondido por el Brian 02.05.2013 - 01:04
2

Para agregar un elemento de menú mediante programación. puedes enganchar al filtro wp_nav_menu_items . coloque el código debajo de su tema functions.php para agregar el ítem del menú de inicio de sesión / cierre de sesión en el menú principal. 'Primario' es el nombre / id del menú registrado.

/**
 * 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;
}
    
respondido por el Aamer Shahzad 08.03.2016 - 19:49

Lea otras preguntas en las etiquetas