wordpress - 当对产品使用多个类别时,产品页面上的面包屑不会反射(reflect)当前的 url/slug

标签 wordpress woocommerce hook-woocommerce breadcrumbs

我的 WordPress 网站使用 Woocommerce 来销售产品。但是,当您为产品分配多个产品类别并访问产品页面(将 Product Permalinks 设置为 Shop base with category )时,会发生意外情况。指向(父)类别的面包屑链接始终是相同的,并且不反射(reflect)导航的 URL。 (这与 here 描述的问题相同。)

问题总结:

<表类=“s-表”> <标题> 导航至 面包屑链接 预期的面包屑链接 <正文> /shop/category-1/sample-product/ 类别2 类别1 /shop/category-2/sample-product/ 类别2 类别2

我在任何解决此问题的来源上都没有找到真正的答案。 (我认为它应该被修复,但有些人可能会说这是出于搜索引擎优化的原因,防止重复的网站内容。)因此,为了帮助任何人寻找答案,这里是:

最佳答案

(wr)(g) 发生了什么?

产品页面上的面包屑由 woocommerce_breadcrumb() function 生成。进而通过 WC_Breadcrumb->generate() 获取它。

进一步遍历代码,您最终会进入 add_crumbs_single() 函数,其中 woocommerce_breadcrumb_product_terms_args 过滤器应用于产品条款提取的排序。 (有关详细信息,请参阅 wp_get_post_termsWP_Term_Query::__construct()。)

从代码中可以清楚地看出,他们优先考虑具有最高 parent 值的术语,换句话说,优先考虑数据库中最新添加的父级的术语。

解决方案1

由于该产品的情况始终相同,因此您可能需要向主题的 function.php 添加一个过滤器(或使用自定义插件)来覆盖此行为。我用这个让我的工作:

function prioritize_current_url_cat_in_breadcrumbs( $args ) {
    // Only if we're on a product page..
    if ( is_product() ) {

        // ..and there's a product category slug in the navigated url..
        $product_cat_slug = get_query_var( 'product_cat', '' );
        if ( ! empty($product_cat_slug) ) {

            // ..which we can find
            $product_cat = get_term_by( 'slug', $product_cat_slug, 'product_cat', ARRAY_A );
            if ( ! empty($product_cat) ) {

                // Then only get that current product category to start the breadcrumb trail
                $args['term_taxonomy_id'] = $product_cat['term_taxonomy_id'];
            }
        }
    }
    return $args;
}
add_filter( 'woocommerce_breadcrumb_product_terms_args', 'prioritize_current_url_cat_in_breadcrumbs' );

add_crumbs_single() 函数的其余部分将负责遍历类别的父级等,直到 Home。

解决方案2

或者,您可以使用 woocommerce_breadcrumb_main_term 过滤器更改用于面包屑路径的“主要术语”。过滤器函数接收 2 个参数:主要术语(如 WP_Term)和包含找到的所有产品类别的 WP_Term 数组。它会返回一个术语,因此您可以搜索数组并选择您想要开始面包屑的正确术语。

function prioritize_current_url_cat( $first_term, $all_terms ) {
    if ( is_product() ) {
        $product_cat_slug = get_query_var( 'product_cat', '' );
        if ( ! empty($product_cat_slug) ) {
            // Get the WP_Term with the current slug
            $filtered_terms = array_values( array_filter($all_terms, function($v) use ($product_cat_slug) {
                return $v->slug === $product_cat_slug;
            }) );
            if ( ! empty($filtered_terms) ) {
                return $filtered_terms[0];
            }
        }
    }
    // Fallback to default
    return $first_term;
}
add_filter( 'woocommerce_breadcrumb_main_term', 'prioritize_current_url_cat', 10, 2 );

希望这可以帮助任何人搜索时间并完成源代码行......!

额外:修复存档页面上的永久链接

要解决产品存档页面上的相同问题,您可以 Hook post_type_link 过滤器,并预先将永久链接的 %product_cat% 部分替换为正确的蛞蝓像这样:

/**
 * Set product link slugs to match the page context,
 * for products with multiple associated categories.
 *
 * For example:
 *   when viewing Category A, use '/category-a/this-product/'
 *   when viewing Category B, use '/category-b/this-product/'
 */
function my_plugin_product_url_use_current_cat( $post_link, $post, $leavename, $sample ) {
    // Get current term slug (used in page url)
    $current_product_term_slug = get_query_var( 'product_cat', '' );
    if ( empty ( $current_product_term_slug ) ) {
        return $post_link;
    }

    if ( is_product_category() ) {
        // Get current term object
        $current_product_term = get_term_by( 'slug', $current_product_term_slug, 'product_cat' );
        if ( FALSE === $current_product_term ) {
            return $post_link;
        }

        // Get all terms associated with product
        $all_product_terms = get_the_terms( $post->ID, 'product_cat' );

        // Filter terms, taking only relevant terms for current term
        $matching_or_descendant_terms = array_filter( array_map( function( $term ) use ( $current_product_term ) {
            // Return term if it is the current term
            if ( $term->term_id === $current_product_term->term_id ) {
                return [ TRUE, $term ];
            }

            // Return term if one of its ancestors is the current term (highest hierarchy first)
            $parent_terms = array_reverse( get_ancestors( $term->term_id, 'product_cat' ) );
            foreach ( $parent_terms as $parent_term_id ) {
                if ( $parent_term_id === $current_product_term->term_id ) {
                    return [ FALSE, $term ];
                }
            }

            // Leave out all others
            return NULL;
        }, $all_product_terms ) );

        if ( count( $matching_or_descendant_terms ) > 0 ) {
            // Sort terms (directly associated first, descendants next)
            usort( $matching_or_descendant_terms, function( $a, $b ) {
                if ( $a[0] === $b[0] ) {
                    return 0;
                } else if ( TRUE === $a[0] ) {
                    return -1;
                } else {
                    return 1;
                }
            } );

            // Get entire slug (including ancestors)
            $slug = get_term_parents_list( $matching_or_descendant_terms[0][1]->term_id, 'product_cat', [
                'format' => 'slug',
                'separator' => '/',
                'link' => false,
                'inclusive' => true,
            ] );

            // Set url slug to closest child term of current term
            // or current term (if directly associated)
            $post_link = str_replace('%product_cat%/', $slug, $post_link);
        }
    } else if ( is_product() ) {
        $post_link = str_replace('%product_cat%', $current_product_term_slug, $post_link);
    }
    return $post_link;
}
add_filter( 'post_type_link', 'my_plugin_product_url_use_current_cat', 10, 4 );

说明

正如 @Markos 提到的,我们试图找出最合乎逻辑和直观的方法来做到这一点。

基本上,它检查当前产品类别(来自 url 的 slug)是否与显示的产品直接关联。如果是这样,请使用该别名作为产品页面的链接。 (使用上述解决方案之一,面包屑会反射(reflect) url 路径以进行直观导航。)

如果当前查看的产品类别与该产品没有直接关联,它将查找第一个匹配的后代(子)类别,并使用该别名作为指向产品页面的链接。

这样,用户始终可以看到他们是如何进入当前产品页面的,并且可以轻松导航回该类别。

注意:如果此代码段没有改变任何内容,请尝试较早的 Hook 优先级和/或检查 $post_link 变量是否包含 %product_cat% 模板部分。

关于wordpress - 当对产品使用多个类别时,产品页面上的面包屑不会反射(reflect)当前的 url/slug,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65803313/

相关文章:

php - 如何制作具有上一页和下一页功能的博客类型页面?

php - 如何在 wordpress/woocommerce 中获取所有订单详细信息?

php - 如何在 woocommerce 中获取应用的优惠券金额?

wordpress - 如何仅返回 "woocommerce_get_product_thumbnail()"中的图像 src ?

php - 可更改 Woocommerce 购物车商品价格的产品自定义复选框选项

wordpress - 如何解决 flutter wordpress json api 错误?

php - Wordpress/Woocommerce 数据发送到 Firebase 数据库

jquery - WordPress 在悬停时只针对一篇文章

php - 如何在 Woocommerce 中选择特定产品时显示不同尺寸

css - WooCommerce 添加到购物车按钮和隐藏价格