añadir clase span dentro de la etiqueta anchor de wp_nav_menu
Encontré ejemplos añadiendo una clase a elementos de nivel superior, para poder mostrar una flecha en elementos del menú con subitems, pero parece terrible lidiar con las clases ya integradas de WordPress, no se puede mostrar la flecha con el estado actual y hover de css, simplemente arruina todos los estados.
El menú de navegación actual es así <li><a>Texto</a></li>
¿Hay alguna manera de añadir un <span class="arrow"></span>
dentro de las etiquetas padre <a></a>
?
Ejemplo,
Añadir ⇒ <span class="arrow"></span>
dentro de ⇒ <a/></a>
etiquetas
Por lo tanto ⇒ <li><a>Texto<span class="arrow"></span></a></li>
que es padre.
El código actual añade las etiquetas <span></span>
fuera de las etiquetas <a></a>
que es padre
class My_Walker_Nav_Menu extends Walker_Nav_Menu {
function start_lvl(&$output, $depth, $args) {
$indent = str_repeat("\t", $depth);
if('primary' == $args->theme_location && $depth ==0){
$output .='<span class="arrow"></span>';
}
$output .= "\n$indent<ul class=\"sub-menu\">\n";
}
}
Título de la pregunta original editado de: "añadir clase span dentro de <a>
"

¿Has intentado usar los parámetros before
o link_before
en los argumentos de tu array al declarar la función wp_nav_menu
?
Nota: usa after
o link_after
para el efecto opuesto.
Ejemplo:
wp_nav_menu(
//argumentos normales aquí...etc
'before' => '<span class="arrow"></span>',
//o 'link_before' => '<span class="arrow"></span>',
);
Del Codex:
$before
(string) (opcional) Texto de salida antes del del enlace
Por defecto: Ninguno
ej. 'before' => ''
o...
$link_before
(string) (opcional) Texto de salida antes del texto del enlace
Por defecto: Ninguno
ej. 'link_before' => ''
Recursos de apoyo:

Esto crea dos instancias donde muestra una clase span dentro de la etiqueta en los niveles primario y secundario, para que puedas agregar diferentes imágenes a tu clase span con fines de diseño y navegación.
Esto ayuda a los usuarios y desarrolladores a mostrar si hay un menú desplegable en el encabezado y también facilita la navegación dentro del sitio web.
1. Primero agrega este código a tu functions.php
class Nav_Walker_Nav_Menu extends Walker_Nav_Menu {
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $class_names .'>';
$attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : '';
$attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : '';
$attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : '';
$attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : '';
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
if ( 'primary' == $args->theme_location ) {
$submenus = 0 == $depth || 1 == $depth ? get_posts( array( 'post_type' => 'nav_menu_item', 'numberposts' => 1, 'meta_query' => array( array( 'key' => '_menu_item_menu_item_parent', 'value' => $item->ID, 'fields' => 'ids' ) ) ) ) : false;
$item_output .= ! empty( $submenus ) ? ( 0 == $depth ? '<span class="arrow"></span>' : '<span class="sub-arrow"></span>' ) : '';
}
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
2. Agrega este código en tu header.php donde esté instalado tu wp_nav_menu
Se explica a continuación cómo instalar el nuevo menú personalizado, en este caso sería Nav_Walker_Nav_Menu.
<?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary', 'walker' => new Nav_Walker_Nav_Menu() ) ); ?>
3. Agrega algo de CSS
Para que pueda mostrar tus nuevas imágenes de flecha span dentro de tus etiquetas en nivel primario y secundario.
#menu-header-menu li span.arrow { height:12px;background-image: url("images/nav-arrows.png");background-position: -8px -3px;background-repeat: no-repeat;float: right;margin: 0 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu li a:hover span.arrow{ height:12px;background-image: url("images/nav-arrows.png");background-position: -39px -3px;background-repeat: no-repeat;float: right;margin: 0 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu ul.sub-menu li span.sub-arrow { height:12px;background-image: url("images/nav-arrows.png");background-position: -8px -39px;background-repeat: no-repeat;float: right;margin: -2px 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu ul.sub-menu li a:hover span.sub-arrow{ height:12px;background-image: url("images/nav-arrows.png");background-position: -39px -39px;background-repeat: no-repeat;float: right;margin: -2px 0px 0 10px;text-indent: -9999px;width: 12px;}
¡Espero que esto ayude! :)

Ambas respuestas publicadas por userabuser y wordpress_designer son excelentes, pero me gustaría publicar una respuesta que es una combinación de las dos.
Con esta respuesta puedes usar lógica para definir dónde no quieres que se aplique el link_before
. Así como también qué quieres poner antes del texto del enlace.
Primero crea una clase muy simple como la que se muestra a continuación. Esta clase en realidad solo es responsable de verificar cuando el elemento no es un submenú ($depth <= 0
) y para limpiar y recordar el valor de link_before
.
if ( ! class_exists('PREFIX_Menu_Walker')) {
class PREFIX_Menu_Walker extends Walker_Nav_Menu {
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$before = property_exists($args, 'link_before') ? $args->link_before : '';
// Vaciar el `link_before` al navegar sobre un elemento de nivel raíz
if ($depth <= 0 && !empty($before)) {
$args->link_before = '';
}
// Continuar con la clase predeterminada/núcleo del walker de menú de WordPress
parent::start_el( $output, $item, $depth, $args, $id );
// Recordar qué `link_before` $args estaban establecidos.
$args->link_before = $before;
}
}
}
Lo segundo que tendrás que hacer es aplicar el argumento walker
y el argumento link_before
a tu array de wp_nav_menu
, así:
wp_nav_menu([
'link_before' => '<span>Hola</span>',
'walker' => new PREFIX_Menu_Walker()
]);
