Cómo mostrar submenú usando solamente wp_nav_menu()
Estoy usando este código para mostrar los submenús de páginas personalizadas cuando se está en la página padre. Pero este código también muestra una página padre en una página que no tiene submenú, la cual me gustaría ocultar. Básicamente, solo quiero usar este código si estamos en una página que tiene una subpágina.
class Selective_Walker extends Walker_Nav_Menu
{
function walk( $elements, $max_depth) {
$args = array_slice(func_get_args(), 2);
$output = '';
if ($max_depth < -1) //parámetro inválido
return $output;
if (empty($elements)) //nada que recorrer
return $output;
$id_field = $this->db_fields['id'];
$parent_field = $this->db_fields['parent'];
// visualización plana
if ( -1 == $max_depth ) {
$empty_array = array();
foreach ( $elements as $e )
$this->display_element( $e, $empty_array, 1, 0, $args, $output );
return $output;
}
/*
* necesita mostrar en orden jerárquico
* separa elementos en dos grupos: elementos de nivel superior y elementos hijos
* children_elements es un array bidimensional, por ejemplo
* children_elements[10][] contiene todos los sub-elementos cuyo padre es 10.
*/
$top_level_elements = array();
$children_elements = array();
foreach ( $elements as $e) {
if ( 0 == $e->$parent_field )
$top_level_elements[] = $e;
else
$children_elements[ $e->$parent_field ][] = $e;
}
/*
* cuando ninguno de los elementos es de nivel superior
* asume que el primero debe ser la raíz de los sub elementos
*/
if ( empty($top_level_elements) ) {
$first = array_slice( $elements, 0, 1 );
$root = $first[0];
$top_level_elements = array();
$children_elements = array();
foreach ( $elements as $e) {
if ( $root->$parent_field == $e->$parent_field )
$top_level_elements[] = $e;
else
$children_elements[ $e->$parent_field ][] = $e;
}
}
$current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' ); //añadido por continent7
foreach ( $top_level_elements as $e ){ //modificado por continent7
// desciende solo en el árbol actual
$descend_test = array_intersect( $current_element_markers, $e->classes );
if ( !empty( $descend_test ) )
$this->display_element( $e, $children_elements, 2, 0, $args, $output );
}
/*
* si estamos mostrando todos los niveles y children_elements restante no está vacío,
* entonces tenemos huérfanos, que deberían mostrarse de todos modos
*/
/* eliminado por continent7
if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
$empty_array = array();
foreach ( $children_elements as $orphans )
foreach( $orphans as $op )
$this->display_element( $op, $empty_array, 1, 0, $args, $output );
}
*/
return $output;
}
}
en la plantilla usando:
wp_nav_menu(
array(
'theme_location'=>'primary',
'walker'=>new Selective_Walker()
)
);
He tenido este mismo problema muchas veces en el pasado con WordPress. En otros CMS que he utilizado, los menús siempre tenían una opción para start_depth (profundidad inicial), lo que hacía muy fácil implementar un menú secundario o terciario (menú dividido).
WordPress no incluye esta función; y muchas de las soluciones que encuentras en línea usan wp_list_pages, lo que ignora completamente la jerarquía del administrador de menús.
Después de probar diferentes walkers y widgets, finalmente decidí crear mi propio plugin que incluye la opción start_depth.
Se usa así:
wp_nav_menu(array('theme_location' => 'primary_navigation', 'start_depth' => 1));
Para quien esté interesado, pueden obtenerlo gratis en el repositorio de plugins de WordPress: https://wordpress.org/plugins/wp-nav-plus/

¡He creado un plugin gratuito que resuelve este problema!
https://wordpress.org/plugins/wp-nav-menu-extended/
Este plugin extiende la función nativa wp_nav_menu y añade opciones adicionales:
- level : (integer) (requerido para que funcione este plugin) El nivel del menú de navegación a mostrar. Si no se pasa el parámetro child_of, muestra todos los elementos de este nivel
- child_of : (string|integer) (opcional) Puede ser el título o el ID del elemento padre en el menú cuyos hijos directos se mostrarán
Ejemplo de uso:
$defaults = array( 'theme_location' => 'main_menu', 'level' => 2, 'child_of' => 'About Us', );
wp_nav_menu( $defaults );
