one
<?php
/**
* Dynamic Breadcrumb Function
*
* Outputs a breadcrumb trail for any WordPress page, post, CPT,
* taxonomy archive, search results, or 404 page.
*
* Usage: <?php minglu_breadcrumbs(); ?>
*
* @param array $args Optional config overrides.
*/
function minglu_breadcrumbs( array $args = [] ): void {
$defaults = [
'separator' => '<span class="breadcrumb__sep">/</span>',
'home_label' => __( 'Home', 'minglu' ),
'show_on_home' => false, // hide breadcrumbs on the front page
];
$args = wp_parse_args( $args, $defaults );
// Optionally hide on the front page.
if ( is_front_page() && ! $args['show_on_home'] ) {
return;
}
global $post;
$sep = $args['separator'];
$crumbs = []; // [ 'label' => string, 'url' => string|null ]
// ── Home ──────────────────────────────────────────────────
$crumbs[] = [
'label' => esc_html( $args['home_label'] ),
'url' => esc_url( home_url( '/' ) ),
];
// ── WooCommerce ───────────────────────────────────────────
if ( function_exists( 'is_woocommerce' ) && is_woocommerce() ) {
// Shop page.
$shop_id = wc_get_page_id( 'shop' );
if ( $shop_id && $shop_id !== -1 ) {
$crumbs[] = [
'label' => esc_html( get_the_title( $shop_id ) ),
'url' => esc_url( get_permalink( $shop_id ) ),
];
}
if ( is_product_category() || is_product_tag() ) {
$term = get_queried_object();
// Ancestor categories.
if ( $term->parent ) {
foreach ( array_reverse( get_ancestors( $term->term_id, 'product_cat' ) ) as $ancestor_id ) {
$ancestor = get_term( $ancestor_id, 'product_cat' );
$crumbs[] = [
'label' => esc_html( $ancestor->name ),
'url' => esc_url( get_term_link( $ancestor ) ),
];
}
}
// Current term — no link (last crumb).
$crumbs[] = [ 'label' => esc_html( $term->name ), 'url' => null ];
} elseif ( is_product() ) {
// Product category trail above the product.
$categories = get_the_terms( $post->ID, 'product_cat' );
if ( $categories && ! is_wp_error( $categories ) ) {
$cat = current( $categories );
foreach ( array_reverse( get_ancestors( $cat->term_id, 'product_cat' ) ) as $ancestor_id ) {
$ancestor = get_term( $ancestor_id, 'product_cat' );
$crumbs[] = [
'label' => esc_html( $ancestor->name ),
'url' => esc_url( get_term_link( $ancestor ) ),
];
}
$crumbs[] = [
'label' => esc_html( $cat->name ),
'url' => esc_url( get_term_link( $cat ) ),
];
}
$crumbs[] = [ 'label' => esc_html( get_the_title() ), 'url' => null ];
}
// ── Standard taxonomy archive ─────────────────────────────
} elseif ( is_tax() || is_category() || is_tag() ) {
$term = get_queried_object();
// Walk up ancestor chain.
if ( ! empty( $term->parent ) ) {
$taxonomy = $term->taxonomy;
foreach ( array_reverse( get_ancestors( $term->term_id, $taxonomy ) ) as $ancestor_id ) {
$ancestor = get_term( $ancestor_id, $taxonomy );
$crumbs[] = [
'label' => esc_html( $ancestor->name ),
'url' => esc_url( get_term_link( $ancestor ) ),
];
}
}
$crumbs[] = [ 'label' => esc_html( $term->name ), 'url' => null ];
// ── Single post / CPT ─────────────────────────────────────
} elseif ( is_single() ) {
$post_type = get_post_type();
if ( 'post' === $post_type ) {
// Primary category (Yoast) or first assigned category.
$primary_id = get_post_meta( $post->ID, '_yoast_wpseo_primary_category', true );
$categories = get_the_category();
if ( $primary_id ) {
$cat = get_category( (int) $primary_id );
} elseif ( ! empty( $categories ) ) {
$cat = $categories[0];
}
if ( ! empty( $cat ) ) {
foreach ( array_reverse( get_ancestors( $cat->term_id, 'category' ) ) as $ancestor_id ) {
$ancestor = get_category( $ancestor_id );
$crumbs[] = [
'label' => esc_html( $ancestor->name ),
'url' => esc_url( get_category_link( $ancestor->term_id ) ),
];
}
$crumbs[] = [
'label' => esc_html( $cat->name ),
'url' => esc_url( get_category_link( $cat->term_id ) ),
];
}
} else {
// Custom post type — link its archive if one exists.
$pto = get_post_type_object( $post_type );
if ( $pto && $pto->has_archive ) {
$crumbs[] = [
'label' => esc_html( $pto->labels->name ),
'url' => esc_url( get_post_type_archive_link( $post_type ) ),
];
}
}
$crumbs[] = [ 'label' => esc_html( get_the_title() ), 'url' => null ];
// ── Hierarchical pages ────────────────────────────────────
} elseif ( is_page() ) {
if ( $post->post_parent ) {
foreach ( array_reverse( get_post_ancestors( $post->ID ) ) as $ancestor_id ) {
$crumbs[] = [
'label' => esc_html( get_the_title( $ancestor_id ) ),
'url' => esc_url( get_permalink( $ancestor_id ) ),
];
}
}
$crumbs[] = [ 'label' => esc_html( get_the_title() ), 'url' => null ];
// ── CPT archive ───────────────────────────────────────────
} elseif ( is_post_type_archive() ) {
$crumbs[] = [ 'label' => esc_html( post_type_archive_title( '', false ) ), 'url' => null ];
// ── Author archive ────────────────────────────────────────
} elseif ( is_author() ) {
$crumbs[] = [ 'label' => esc_html( get_queried_object()->display_name ), 'url' => null ];
// ── Date archive ──────────────────────────────────────────
} elseif ( is_year() ) {
$crumbs[] = [ 'label' => get_the_date( 'Y' ), 'url' => null ];
} elseif ( is_month() ) {
$crumbs[] = [
'label' => get_the_date( 'Y' ),
'url' => esc_url( get_year_link( get_the_date( 'Y' ) ) ),
];
$crumbs[] = [ 'label' => get_the_date( 'F Y' ), 'url' => null ];
} elseif ( is_day() ) {
$crumbs[] = [
'label' => get_the_date( 'Y' ),
'url' => esc_url( get_year_link( get_the_date( 'Y' ) ) ),
];
$crumbs[] = [
'label' => get_the_date( 'F Y' ),
'url' => esc_url( get_month_link( get_the_date( 'Y' ), get_the_date( 'm' ) ) ),
];
$crumbs[] = [ 'label' => get_the_date(), 'url' => null ];
// ── Search results ────────────────────────────────────────
} elseif ( is_search() ) {
$crumbs[] = [
/* translators: %s: search query */
'label' => sprintf( esc_html__( 'Search: %s', 'minglu' ), esc_html( get_search_query() ) ),
'url' => null,
];
// ── 404 ───────────────────────────────────────────────────
} elseif ( is_404() ) {
$crumbs[] = [ 'label' => esc_html__( 'Page Not Found', 'minglu' ), 'url' => null ];
}
// ── Render ────────────────────────────────────────────────
$last_index = count( $crumbs ) - 1;
?>
<div class="breadcrumb" id="breadcrumb">
<div class="breadcrumb__container">
<?php foreach ( $crumbs as $index => $crumb ) :
$is_last = ( $index === $last_index );
?>
<?php if ( $index > 0 ) : ?>
<?php echo $sep; // Already escaped above. ?>
<?php endif; ?>
<?php if ( ! $is_last && $crumb['url'] ) : ?>
<a href="<?php echo $crumb['url']; ?>"><?php echo $crumb['label']; ?></a>
<?php else : ?>
<span <?php echo $is_last ? 'id="breadcrumbTitle"' : ''; ?>><?php echo $crumb['label']; ?></span>
<?php endif; ?>
<?php endforeach; ?>
</div>
</div>
<?php
}
two
<?php
/**
* Dynamic WordPress Breadcrumbs Function
* * Replaces static HTML breadcrumbs with a fully dynamic, SEO-friendly,
* and context-aware breadcrumb menu matching your CSS classes.
*
* @param array $args Optional arguments to customize labels and behavior.
* @return void Prints the breadcrumb HTML.
*/
function custom_breadcrumbs( $args = array() ) {
// Only run on front-end, and skip on the homepage/frontpage unless specified
if ( is_front_page() || is_home() ) {
return;
}
// Default configuration arguments
$defaults = array(
'separator' => '/', // Your design separator character
'home_label' => __( 'Home', 'text-domain' ),
'show_current' => true, // Show the current page title at the end
'container_class'=> 'breadcrumb',
'inner_class' => 'breadcrumb__container',
'sep_class' => 'breadcrumb__sep',
'current_id' => 'breadcrumbTitle',
);
// Merge user arguments with defaults
$args = wp_parse_args( $args, $defaults );
global $post;
// Array to hold breadcrumb items: array( 'url' => '', 'label' => '' )
$crumbs = array();
// 1. Always start with the Home Link
$crumbs[] = array(
'url' => home_url( '/' ),
'label' => $args['home_label']
);
// 2. Determine Page Context and Build the Hierarchy
if ( is_page() && ! is_front_page() ) {
// Handle hierarchical Pages
if ( $post->post_parent ) {
$ancestors = array_reverse( get_post_ancestors( $post->ID ) );
foreach ( $ancestors as $ancestor_id ) {
$crumbs[] = array(
'url' => get_permalink( $ancestor_id ),
'label' => get_the_title( $ancestor_id )
);
}
}
$crumbs[] = array(
'url' => '',
'label' => get_the_title()
);
} elseif ( is_single() ) {
// Handle Single Posts (including Custom Post Types)
$post_type = get_post_type();
if ( $post_type !== 'post' ) {
// For Custom Post Types, attempt to get the CPT Archive page first
$post_type_object = get_post_type_object( $post_type );
$archive_link = get_post_type_archive_link( $post_type );
if ( $archive_link ) {
$crumbs[] = array(
'url' => $archive_link,
'label' => $post_type_object->labels->name
);
}
// Handle custom taxonomies if associated with CPT
$taxonomies = get_object_taxonomies( $post_type, 'objects' );
if ( ! empty( $taxonomies ) ) {
// Grab the first custom taxonomy assigned to this post
foreach ( $taxonomies as $tax_name => $tax_obj ) {
if ( $tax_obj->hierarchical ) {
$terms = get_the_terms( $post->ID, $tax_name );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
$main_term = $terms[0];
// Get term ancestors if any
$term_ancestors = array_reverse( get_ancestors( $main_term->term_id, $tax_name ) );
foreach ( $term_ancestors as $ancestor_id ) {
$ancestor_term = get_term( $ancestor_id, $tax_name );
$crumbs[] = array(
'url' => get_term_link( $ancestor_term ),
'label' => $ancestor_term->name
);
}
$crumbs[] = array(
'url' => get_term_link( $main_term ),
'label' => $main_term->name
);
break; // Stop after first taxonomy found
}
}
}
}
} else {
// Standard Blog Post: Get category hierarchy
$categories = get_the_category();
if ( ! empty( $categories ) ) {
// Respect Yoast Primary Category if installed, otherwise grab the first category
$primary_cat_id = class_exists( 'WPSEO_Primary_Term' )
? ( new WPSEO_Primary_Term( 'category', $post->ID ) )->get_primary_term()
: null;
$category = $primary_cat_id ? get_term( $primary_cat_id ) : $categories[0];
// Fetch category ancestors
$cat_ancestors = array_reverse( get_ancestors( $category->term_id, 'category' ) );
foreach ( $cat_ancestors as $ancestor_id ) {
$ancestor_cat = get_category( $ancestor_id );
$crumbs[] = array(
'url' => get_category_link( $ancestor_id ),
'label' => $ancestor_cat->name
);
}
$crumbs[] = array(
'url' => get_category_link( $category->term_id ),
'label' => $category->name
);
}
}
$crumbs[] = array(
'url' => '',
'label' => get_the_title()
);
} elseif ( is_category() ) {
// Category Archive
$current_cat = get_queried_object();
if ( $current_cat->parent ) {
$cat_ancestors = array_reverse( get_ancestors( $current_cat->term_id, 'category' ) );
foreach ( $cat_ancestors as $ancestor_id ) {
$ancestor_cat = get_category( $ancestor_id );
$crumbs[] = array(
'url' => get_category_link( $ancestor_id ),
'label' => $ancestor_cat->name
);
}
}
$crumbs[] = array(
'url' => '',
'label' => $current_cat->name
);
} elseif ( is_tag() ) {
// Tag Archive
$crumbs[] = array(
'url' => '',
'label' => single_tag_title( '', false )
);
} elseif ( is_tax() ) {
// Custom Taxonomy Archive
$current_term = get_queried_object();
$taxonomy = $current_term->taxonomy;
if ( $current_term->parent ) {
$term_ancestors = array_reverse( get_ancestors( $current_term->term_id, $taxonomy ) );
foreach ( $term_ancestors as $ancestor_id ) {
$ancestor_term = get_term( $ancestor_id, $taxonomy );
$crumbs[] = array(
'url' => get_term_link( $ancestor_term ),
'label' => $ancestor_term->name
);
}
}
$crumbs[] = array(
'url' => '',
'label' => $current_term->name
);
} elseif ( is_post_type_archive() ) {
// Custom Post Type Archive Page
$post_type_object = get_queried_object();
$crumbs[] = array(
'url' => '',
'label' => $post_type_object->labels->name
);
} elseif ( is_search() ) {
// Search Results Page
$crumbs[] = array(
'url' => '',
'label' => sprintf( __( 'Search results for: "%s"', 'text-domain' ), get_search_query() )
);
} elseif ( is_day() ) {
// Daily Archive
$crumbs[] = array(
'url' => '',
'label' => get_the_date()
);
} elseif ( is_month() ) {
// Monthly Archive
$crumbs[] = array(
'url' => '',
'label' => get_the_date( 'F Y' )
);
} elseif ( is_year() ) {
// Yearly Archive
$crumbs[] = array(
'url' => '',
'label' => get_the_date( 'Y' )
);
} elseif ( is_author() ) {
// Author Archive
$author = get_queried_object();
$crumbs[] = array(
'url' => '',
'label' => sprintf( __( 'Articles by: %s', 'text-domain' ), $author->display_name )
);
} elseif ( is_404() ) {
// 404 Error Page
$crumbs[] = array(
'url' => '',
'label' => __( 'Page Not Found', 'text-domain' )
);
}
// 3. Render Output
if ( ! empty( $crumbs ) ) {
echo '<div class="' . esc_attr( $args['container_class'] ) . '" id="breadcrumb">';
echo '<div class="' . esc_attr( $args['inner_class'] ) . '">';
$total_crumbs = count( $crumbs );
foreach ( $crumbs as $index => $crumb ) {
$is_last = ( $index === $total_crumbs - 1 );
if ( $is_last ) {
// The current page is always unlinked and styled with the unique ID
if ( $args['show_current'] ) {
echo '<span id="' . esc_attr( $args['current_id'] ) . '">' . esc_html( $crumb['label'] ) . '</span>';
}
} else {
// Normal linked breadcrumb
echo '<a href="' . esc_url( $crumb['url'] ) . '">' . esc_html( $crumb['label'] ) . '</a>';
// Add separator
echo '<span class="' . esc_attr( $args['sep_class'] ) . '">' . esc_html( $args['separator'] ) . '</span>';
}
}
echo '</div>';
echo '</div>';
}
}
WP开发教程 WordPress导师在线教程