Cómo agregar un submenú a un menú generado por wp_nav_menu usando un plugin
Tengo un menú generado por wp_nav_menu
que se ve así
<ul class="nav-menu" id="menu-top-nav">
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-43" id="menu-item-43"><a href="http://www.example.com/item1.com">Elemento 1</a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-44" id="menu-item-44"><a href="http://www.example.com/item2.com">Elemento 2</a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-45" id="menu-item-45"><a href="http://www.example.com/item3.com">Elemento 3</a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-46" id="menu-item-46"><a href="http://www.example.com/item4.com">Elemento 4</a></li>
</ul>
Quiero modificar el menú anterior agregando un submenú al "Elemento 3" usando mi plugin, así que esta es mi salida deseada.
<ul class="nav-menu" id="menu-top-nav"><li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-43" id="menu-item-43"><a href="http://www.example.com/item1.com">Elemento 1</a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-44" id="menu-item-44"><a href="http://www.example.com/item2.com">Elemento 2</a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-45" id="menu-item-45"><a href="http://www.example.com/item3.com">Elemento 3</a>
<ul class="sub-menu">
<li class="menu-item" id="menu-item-48"><a href="http://www.example.com/child1.com">hijo 1</a></li>
<li class="menu-item" id="menu-item-49"><a href="http://www.example.com/child2.com">hijo 2</a></li>
<li class="menu-item" id="menu-item-50"><a href="http://www.example.com/child3.com">hijo 3</a></li>
</ul>
</li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-46" id="menu-item-46"><a href="http://www.example.com/item4.com">Elemento 4</a></li>
</ul>
He probado los siguientes filtros pero no me ayudaron a lograr la salida anterior.
wp_setup_nav_menu_item
wp_get_nav_menu_items
wp_nav_menu_items
Solución alternativa 1:
add_filter('wp_nav_menu_items', 'my_custom_menu_item', 10, 2);
function my_custom_menu_item($items, $args)
{
// Número del elemento padre
$parent_item_number = 3;
$pos = nth_strpos($items, '</a>', $parent_item_number) + 4;
$cat_id = 9;
$args = array('numberposts' => 5, 'category' => $cat_id);
$myposts = get_posts($args);
if (!empty($myposts))
{
$str_to_insert = '<ul class="sub-menu">';
global $post;
foreach ($myposts as $post) :
setup_postdata($post);
$str_to_insert .= '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
endforeach;
$str_to_insert .= '</ul>';
$items = substr($items, 0, $pos) . $str_to_insert . substr($items, $pos);
}
return $items;
}
function nth_strpos($str, $substr, $n, $stri = false)
{
if ($stri)
{
$str = strtolower($str);
$substr = strtolower($substr);
}
$ct = 0;
$pos = 0;
while (($pos = strpos($str, $substr, $pos)) !== false)
{
if (++$ct == $n)
{
return $pos;
}
$pos++;
}
return false;
}
La solución anterior funciona pero creo que no es la forma adecuada de lograr el resultado deseado. Me encantaría tener una buena solución de su parte.

Puedes modificar tu menú utilizando un walker.
include('subMenu.php');
$menu = wp_nav_menu( array('menu' => 'YOUR-MENU-NAME','menu_class' => 'megamenu','walker' => new subMenu));
Crea un archivo subMenu.php en la carpeta del tema y añade el siguiente código.
<?php
class subMenu extends Walker_Nav_Menu {
function end_el(&$output, $item, $depth=0, $args=array()) {
if( 'Item 3' == $item->title ){
$output .= '<ul class="sub-menu">
<li class="menu-item" id="menu-item-48"><a href="http://www.example.com/child1.com">child 1</a></li>
<li class="menu-item" id="menu-item-49"><a href="http://www.example.com/child2.com">child 2</a></li>
<li class="menu-item" id="menu-item-50"><a href="http://www.example.com/child3.com">child 3</a></li>
</ul>';
}
$output .= "</li>\n";
}
}

El Hook wp_nav_menu_items
es el correcto si deseas añadir elementos a la estructura del menú de navegación de WordPress.
Mira el ejemplo a continuación para añadir un enlace estático a "Inicio". El enlace es estático, proviene de la función home_url()
y lo incrusto únicamente en los argumentos del menú de navegación de WordPress para los valores before y after. El elemento li es estático, solo se modifica en WordPress si utilizas un Walker para este elemento. El hook wp_nav_menu_items
se encuentra dentro de la lista ul
. Después de definir la variable para el contenido de este nuevo elemento, lo añado a la lista predeterminada en la variable $items
, establecida antes de la salida de la lista. Ahora solo queda devolver todo el contenido.
add_filter( 'wp_nav_menu_items', 'fb_add_home_link', 10, 2 );
function fb_add_home_link( $items, $args ) {
$home_item =
'<li>' .
$args->before .
'<a href="' . home_url( '/' ) . '" title="Inicio">' .
$args->link_before . __( 'Inicio' ) . $args->link_after .
'</a>' .
$args->after .
'</li>';
$items = $home_item . $items;
return $items;
}

Parece que no leíste mi enunciado del problema, así que tu solución no es lo que necesito. No necesito adjuntar un elemento al inicio o al final del menú, sino que necesito un submenú bajo un elemento padre específico. Por favor, lee la pregunta, todo está explicado con claridad.
