Cómo codificar elementos personalizados del menú de forma manual
¿Hay alguna manera de codificar manualmente los elementos del menú personalizado cuando se instala el tema por primera vez? Estoy creando un tema que creará automáticamente algunas páginas comunes cuando se instale. Necesito saber si también puedo agregarlas al menú personalizado de WordPress para que el cliente no necesite agregarlas manualmente.
En otras palabras: ¿cómo insertar/crear elementos de menú personalizados programáticamente?
Háganme saber si algo no está claro. ¡Cualquier guía a la página del codex apropiada es bienvenida. ¡Gracias!
actualización: probé el código de aquí Apuntando a un menú específico con wp_nav_menu_items
Registro del menú:
function register_my_menus() {
register_nav_menus(
array('main-menu' => __( 'Menú Principal' ) )
);
}
add_action( 'init', 'register_my_menus' );
Uso en la plantilla:
<?php wp_nav_menu( array( 'theme_location' => 'main-menu' ) ); ?>
Código para agregar nuevos elementos:
function new_nav_menu_items($items) {
if( $args->theme_location == 'main-menu' ){
$homelink = '<li class="home"><a href="' . home_url( '/' ) . '">' . __('Inicio') . '</a></li>';
$items = $homelink . $items;
return $items;
}
}
add_filter( 'wp_nav_menu_items', 'new_nav_menu_items', 10, 2 );
Cuando agrego el código para añadir nuevos elementos en el menú de navegación en el archivo functions.php
no sucede nada en la página del menú en el panel de administración, ¡pero los elementos actuales del menú desaparecen en el sitio!

El problema con tu código es que en realidad no está agregando los enlaces al menú, solo a la salida del menú, por eso se usa un filtro (add_filter), así que solo estás filtrando la salida del menú. De hecho, incluso si no tienes un menú, tu enlace se mostrará con el código que estás usando. Pero para crear un enlace y agregarlo a un menú, puedes usar este código:
$run_once = get_option('menu_check');
if (!$run_once){
//asigna un nombre a tu menú
$name = 'menú predeterminado del tema';
//crea el menú
$menu_id = wp_create_nav_menu($name);
//luego obtén el objeto del menú por su nombre
$menu = get_term_by( 'name', $name, 'nav_menu' );
//luego agrega el enlace/ítem del menú y haz esto por cada ítem que quieras agregar
wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Inicio'),
'menu-item-classes' => 'home',
'menu-item-url' => home_url( '/' ),
'menu-item-status' => 'publish'));
//luego asignas la ubicación deseada en el tema
$locations = get_theme_mod('nav_menu_locations');
$locations['main-menu'] = $menu->term_id;
set_theme_mod( 'nav_menu_locations', $locations );
// luego actualizas la opción menu_check para asegurarte de que este código solo se ejecute una vez
update_option('menu_check', true);
}
He comentado todo para hacerlo más simple.
Para crear una página secundaria/subpágina/menú de segundo nivel (como quieras llamarlo), solo necesitas establecer el menu-item-parent-id
en el nuevo ítem, por ejemplo:
//crea el ítem de menú de nivel superior (inicio)
$top_menu = wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Inicio'),
'menu-item-classes' => 'home',
'menu-item-url' => home_url( '/' ),
'menu-item-status' => 'publish'
'menu-item-parent-id' => 0,
));
//Sub ítem de menú (primer hijo)
$first_child = wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Primer_Hijo'),
'menu-item-classes' => 'home',
'menu-item-url' => home_url( '/' ),
'menu-item-status' => 'publish'
'menu-item-parent-id' => $top_menu,
));
//Sub Sub ítem de menú (segundo hijo)
$Second_child = wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Segundo_Hijo'),
'menu-item-classes' => 'home',
'menu-item-url' => home_url( '/' ),
'menu-item-status' => 'publish'
'menu-item-parent-id' => $first_child,
));
También puedes establecer la posición mediante código con menu-item-position
y creo que se hace así:
- Primer ítem - 'menu-item-position' => 1
- Primer hijo del primer ítem - 'menu-item-position' => 1
- Segundo hijo del primer ítem - 'menu-item-position' => 1
- Primer hijo del segundo hijo del primer ítem - 'menu-item-position' => 1
- Segundo ítem - 'menu-item-position' => 2
- 3er ítem - 'menu-item-position' => 3
- 4to ítem - 'menu-item-position' => 4

Esas son las funciones que estaba buscando :) el codex no las incluía :( Una pregunta más, ¿cómo puedo agregar un elemento hijo al elemento Home? Te avisaré en cuanto llegue a mi PC. ¡Gracias!

@Bainternet: obtuve este error al ejecutar el código por primera vez Fatal error: Cannot use object of type stdClass as array in C:\wamp\www\citystir\wp-admin\menu.php on line 25
. Pero el menú se crea y cuando se actualiza la página todo funciona, aunque no aparece nada en la sección Apariencia -> Ubicación del menú en el tema
. ¡Estamos muy cerca! ¡Gracias!

@Bainternet: Mi suposición es que el código está generando un error cuando intenta ejecutar $locations = get_theme_mod('nav_menu_locations');
Así que, el código antes de eso (toda la inserción del menú se completa) se ejecuta pero el código después (establecer la ubicación deseada en el tema) no se ejecuta.

@Sisir: el código funciona perfectamente, ¿cuál es el nombre de la ubicación de tu tema y muéstrame el código exacto que estás usando? Veré si puedo ayudarte.

@Bainternet: Aquí http://pastebin.com/Px16q43a. Usé pastebin.

usé este código en el menú de navegación wp_nav_menu( array( 'theme_location' => 'main-menu' ) );
así que supongo que el nombre de la ubicación del tema es main-menu
, ¿correcto?

sí, pero aún necesitas registrar esta ubicación del tema usando register_nav_menu( $location, $description );
antes de intentar asignar un menú a esa ubicación.

@Bainternet: ¡Gracias! El nombre de la ubicación del tema ahora se muestra. Pero el error seguía ahí hasta que lo puse en una función y luego agregué la función en mi página de opciones del tema. Ahora solo se ejecutará cuando se haga clic en el botón. Parece que así el error desapareció. Todo funciona bien ahora. Gracias por toda tu ayuda. Espero que siempre llegues a mis preguntas ;)

@Bainternet: Hola, he tenido que molestarte de nuevo :) Con la función wp_update_nav_menu_item()
los elementos del menú se agregan como enlaces personalizados. ¿Hay alguna manera de agregar elementos del menú de tipo publicación o página? Esto es porque ahora cuando actualizo mi enlace permanente, los enlaces personalizados no se actualizan. Pero si fuera un elemento del menú de tipo página, se actualizaría automáticamente. Creo que me expliqué bien. ¡Gracias!

@Bainternet: Hola, el atributo menu-item-position
debe ser incremental desde el elemento superior del menú hasta el inferior, sin importar si hay subelementos o no. Encontré esto aquí: http://www.acousticwebdesign.net/wordpress/how-to-create-wordpress-3-navigation-menus-in-your-theme-or-plugin-code/.

Tu código original está muy cerca de ser correcto y realmente creo que esta solución larga de @Bainternet (sin ofender) es excesiva, así que mira esto en su lugar:
function new_nav_menu_items($items, $args) {
if( $args->theme_location == 'primary' ){
$homelink = '<li class="home"><a href="' . home_url( '/' ) . '">' . __('Home') . '</a></li>';
$items = $homelink . $items;
}
return $items;
}
add_filter( 'wp_nav_menu_items', 'new_nav_menu_items', 10, 2 );
Tu único problema era que no estabas devolviendo $items después de que la función verificara el menú correcto, y te faltaba el segundo argumento de callback necesario para hacer la verificación ($args).

Hay un error en WordPress 3.4.2:
Necesitas crear la relación del término manualmente:
$menu = wp_get_nav_menu_object('menú superior'); // Obtiene el objeto del menú llamado 'menú superior'
$id = wp_update_nav_menu_item($menu->term_id, 0, $data); // Actualiza o crea un ítem de menú
if ($menu->term_id && (!is_object_in_term($id, 'nav_menu', (int)$menu->term_id))) {
wp_set_post_terms($id, array((int)$this->id), 'nav_menu'); // Establece la relación del término si no existe
}
Consulta https://gist.github.com/4148529 para ver un ejemplo de la clase Menu para la creación sencilla de menús.
