Contents
Los breadcrumbs (migas de pan) son una ayuda visual y de navegación muy útil en sitios WordPress: mejoran la experiencia de usuario, la accesibilidad y el SEO al mostrar la jerarquía de la página. Usar un plugin no siempre es necesario: con unas pocas líneas de PHP en tu tema puedes crear breadcrumbs simples, ligeros y personalizables, sin sobrecargar la instalación.
Requisitos y dónde colocar el código
Este tutorial asume conocimientos básicos de WordPress y PHP. El código que verás lo puedes añadir en el archivo functions.php de tu tema (o mejor aún, del tema hijo), o encapsularlo en un pequeño plugin si prefieres mantener el código separado del tema.
Objetivos de la función
- Soportar: página de inicio, entradas individuales, páginas anidadas (padres), categorías, etiquetas, taxonomías personalizadas, archivos de tipo de entrada personalizada, archivos por fecha, autor, búsqueda y 404.
- Manejo de paginación (page 2, etc.).
- Opciones configurables: separador, etiqueta de inicio, mostrar/ocultar la página actual y posibilidad de devolver el HTML o imprimirlo directamente.
- Salida semántica y ligera, fácil de estilizar vía CSS.
Inserta la siguiente función en functions.php. Ajusta las opciones por defecto según tus necesidades.
/ , home_label => Inicio, show_on_home => true, // mostrar breadcrumb sólo en home? show_current => true, // mostrar título de la página actual echo => true, // imprimir directamente o devolver string before => , // texto antes del título actual after => , // texto después del título actual ) opts = wp_parse_args( args, defaults ) // No hacer nada si estamos en la página de inicio y no queremos mostrar if ( ( is_front_page() is_home() ) ! opts[show_on_home] ) { return } breadcrumbs = array() // Añadir enlace a inicio home_url = home_url( / ) breadcrumbs[] = . esc_html( opts[home_label] ) . if ( is_front_page() ! is_home() ) { // Página estática como front page if ( opts[show_current] ) { breadcrumbs[] = opts[before] . get_the_title( get_option(page_on_front) ) . opts[after] } } elseif ( is_home() ! is_front_page() ) { // Página principal del blog (listado de entradas) blog_label = get_the_title( get_option(page_for_posts) ) ? get_the_title( get_option(page_for_posts) ) : Blog breadcrumbs[] = opts[before] . esc_html( blog_label ) . opts[after] } elseif ( is_single() ) { post = get_post() post_type = get_post_type( post ) if ( post_type != post ) { // Post type personalizado: mostrar enlace al archivo del CPT si existe pt_obj = get_post_type_object( post_type ) if ( pt_obj ) { archive_link = get_post_type_archive_link( post_type ) if ( archive_link ) { breadcrumbs[] = . esc_html( pt_obj->labels->name ) . } else { // Si no hay archivo, enlazar al singular label breadcrumbs[] = esc_html( pt_obj->labels->singular_name ) } } } else { // Post tipo post: mostrar categorías (primera) categories = get_the_category( post->ID ) if ( ! empty( categories ) ) { // Ordenar por jerarquía, usar la primero que devuelva WordPress category = categories[0] category_links = array() anc = get_ancestors( category->term_id, category ) anc = array_reverse( anc ) foreach ( anc as cat_id ) { cat = get_category( cat_id ) category_links[] = term_id ) ) . > . esc_html( cat->name ) . } category_links[] = term_id ) ) . > . esc_html( category->name ) . breadcrumbs = array_merge( breadcrumbs, category_links ) } } // Añadir título de la entrada actual if ( opts[show_current] ) { breadcrumbs[] = opts[before] . get_the_title() . opts[after] } } elseif ( is_page() ) { // Páginas: mostrar jerarquía de padres global post if ( post->post_parent ) { anc = get_post_ancestors( post->ID ) anc = array_reverse( anc ) foreach ( anc as ancestor_id ) { breadcrumbs[] = . esc_html( get_the_title( ancestor_id ) ) . } } if ( opts[show_current] ) { breadcrumbs[] = opts[before] . get_the_title() . opts[after] } } elseif ( is_category() ) { cat = get_queried_object() if ( cat->parent ) { anc = get_ancestors( cat->term_id, category ) anc = array_reverse( anc ) foreach ( anc as cat_id ) { c = get_category( cat_id ) breadcrumbs[] = term_id ) ) . > . esc_html( c->name ) . } } breadcrumbs[] = opts[before] . single_cat_title( , false ) . opts[after] } elseif ( is_tag() ) { breadcrumbs[] = opts[before] . single_tag_title( , false ) . opts[after] } elseif ( is_tax() ) { // Taxonomía personalizada term = get_queried_object() taxonomy = get_taxonomy( term->taxonomy ) // Si la taxonomía tiene jerarquía if ( term->parent ) { anc = get_ancestors( term->term_id, term->taxonomy ) anc = array_reverse( anc ) foreach ( anc as term_id ) { t = get_term( term_id, term->taxonomy ) breadcrumbs[] = . esc_html( t->name ) . } } breadcrumbs[] = opts[before] . esc_html( term->name ) . opts[after] } elseif ( is_author() ) { author = get_queried_object() breadcrumbs[] = opts[before] . esc_html( author->display_name ) . opts[after] } elseif ( is_search() ) { breadcrumbs[] = opts[before] . sprintf( Resultados de búsqueda: %s, get_search_query() ) . opts[after] } elseif ( is_day() ) { breadcrumbs[] = . get_the_time(Y) . breadcrumbs[] = . get_the_time(F) . breadcrumbs[] = opts[before] . get_the_time(d) . opts[after] } elseif ( is_month() ) { breadcrumbs[] = . get_the_time(Y) . breadcrumbs[] = opts[before] . get_the_time(F) . opts[after] } elseif ( is_year() ) { breadcrumbs[] = opts[before] . get_the_time(Y) . opts[after] } elseif ( is_post_type_archive() ) { post_type = get_query_var( post_type ) if ( is_array( post_type ) ) { post_type = reset( post_type ) } pt_obj = get_post_type_object( post_type ) if ( pt_obj ) { breadcrumbs[] = opts[before] . esc_html( pt_obj->labels->name ) . opts[after] } } elseif ( is_404() ) { breadcrumbs[] = opts[before] . 404 . opts[after] } // Paginación: si hay paged paged = get_query_var( paged ) if ( paged paged > 1 ) { breadcrumbs[] = Página . intval( paged ) } // Construir salida uniendo con separador output = implode( opts[separator], breadcrumbs ) // Envolver enpara salida (es sencillo y fácil de estilizar) html =
if ( opts[echo] ) { echo html } else { return html } } ?>
Cómo llamar a la función desde las plantillas
Coloca la llamada en el archivo de tu tema donde quieras que aparezcan las migas (por ejemplo header.php, single.php, page.php o dentro de un template-part):
Si prefieres devolver el HTML para manipularlo antes de imprimir:
false ) ) echo?>
Ejemplos de configuración
- Usar separador > y ocultar la última parte:
> , show_current => false ) ) ?>
- Etiqueta de inicio personalizada y devolver HTML:
Mi Sitio, echo => false ) ) ?>
Estilos CSS recomendados
Este CSS básico te ayudará a que las migas se vean bien en la mayoría de los temas. Ajusta colores, tamaños y espaciado según tu diseño.
.breadcrumbs { font-size: 13px color: #666 margin: 12px 0 } .breadcrumbs a { color: #0073aa text-decoration: none } .breadcrumbs a:hover { text-decoration: underline } .breadcrumbs a:after { / nada aquí: el separador lo pone PHP si prefieres, elimina separador en PHP y lo añades con CSS / }
Consideraciones y mejoras
- Accesibilidad: hemos usado aria-label en el párrafo si prefieres una estructura más semántica, usa un elemento nav con role y list items, pero si tu theme requiere solo etiquetas permitidas, mantén p y enlaces con texto claro.
- Schema.org: para SEO puedes añadir microdatos (itemtype/itemprop) a los enlaces o generar JSON-LD. Si necesitas microdatos, recuerda adaptar los atributos de las etiquetas HTML en la función.
- Rendimiento: esta implementación es muy ligera frente a plugins que añaden funciones extra. Es apta para la mayoría de sitios.
- Soporte para taxonomías complejas: la función incluye manejo básico de taxonomías jerárquicas si tu proyecto tiene taxonomías no jerárquicas o reglas especiales, añade los casos específicos.
- Internacionalización: para proyectos multilenguaje, envuelve etiquetas estáticas en funciones __() o _e() y asegúrate de traducir Inicio u otros textos.
Casos prácticos y notas sobre comportamiento
- Páginas anidadas: la función recorre ancestros con get_post_ancestors y los muestra en orden jerárquico.
- Entradas: intenta mostrar la categoría principal si deseas otra lógica (por ejemplo la categoría más profunda o la favorita), modifica la selección de categoría.
- Custom Post Types (CPT): si tu CPT tiene archivo habilitado, la función enlaza al archivo del CPT y muestra su label. Si no tiene archivo, muestra el label singular.
- Paginación: añade Página X si el query está paginado.
- 404: muestra simplemente 404 para que el usuario sepa dónde está.
Conclusión
Con unas decenas de líneas en functions.php tienes un breadcrumb funcional, ligero y personalizable, sin necesidad de instalar plugins. La función es una base sólida: puedes extenderla añadiendo microdatos, mejorando la lógica de selección de categoría para posts, o integrando con frameworks de temas.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |