You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为WooCommerce循环加入购物车链接添加自定义类及解决筛选差异

WooCommerce订阅商品按钮添加CSS类的问题排查与修复

问题背景

我们需要修改现有PHP代码,给特定WooCommerce加入购物车按钮添加CSS类ActiveSubscription。原代码可将不可购买商品的循环加入购物车按钮文本改为“Active”,但新增的添加类代码出现筛选不一致问题:原代码能选中3个订阅商品修改文本,新增代码仅选中2个,而“我的账户”页面显示有3个活跃订阅,需排查差异原因。

原功能代码(修改按钮文本)

/**
 * @snippet       Read more > Out of stock @ WooCommerce Shop
 * @how-to        businessbloomer.com/woocommerce-customization
 * @author        Rodolfo Melogli, Business Bloomer
 * @testedwith    WooCommerce 5
 * @community     https://businessbloomer.com/club/
 * See: https://www.businessbloomer.com/woocommerce-rename-read-more-out-of-stock-shop/
 */
 
add_filter( 'woocommerce_product_add_to_cart_text', 'bbloomer_archive_custom_cart_button_text' );
  
function bbloomer_archive_custom_cart_button_text( $text ) {
   global $product;       
   if ( $product && ! $product->is_purchasable() ) {         /* original example was:    ! $product->is_in_stock()  */
      return 'Active';
   } 
   return $text;
}

原代码生成的HTML结构

<p class="product woocommerce add_to_cart_inline " style="">
       <span class="woocommerce-Price-amount amount"><bdi>
       <span class="woocommerce-Price-currencySymbol">£</span>0.00</bdi></span> 
       <span class="subscription-details"> for 2 years</span><br>
       <a href=".../membership/arts-events-marketing-subscription-copy/" 
aria-describedby="woocommerce_loop_add_to_cart_link_describedby_2242" data-quantity="1" 
class="button product_type_subscription" data-product_id="2242" data-product_sku="" 
aria-label="Read more about “Arts Events Marketing Subscription”" 
rel="nofollow" data-success_message="" data-product_price="0.0" 
data-product_name="Arts Events Marketing Subscription" data-google_product_id="">Active</a> 
       <span id="woocommerce_loop_add_to_cart_link_describedby_2242" class="screen-reader-text"></span>
</p>

修改后的完整代码(尝试添加CSS类)

/**
 * @snippet       Read more > Out of stock @ WooCommerce Shop
 * @how-to        businessbloomer.com/woocommerce-customization
 * @author        Rodolfo Melogli, Business Bloomer
 * @testedwith    WooCommerce 5
 * @community     https://businessbloomer.com/club/
 * See: https://www.businessbloomer.com/woocommerce-rename-read-more-out-of-stock-shop/
 */
 
add_filter( 'woocommerce_product_add_to_cart_text', 'bbloomer_archive_custom_cart_button_text' );
  
function bbloomer_archive_custom_cart_button_text( $text ) {
   global $product;       
   if ( $product && ! $product->is_purchasable() ) {         /* original example was:    ! $product->is_in_stock()  */
      return 'Active';
   } 
   return $text;
}

/* Also add a class so that custom css can grey-out the button */

add_filter( 'woocommerce_loop_add_to_cart_link', 'filter_loop_add_to_cart_link', 10, 2 );

function filter_loop_add_to_cart_link( $link, $product ) {
    // Check if the product is part of an active subscription for the current user
    // if ( wcs_user_has_subscription( get_current_user_id(), $product->get_id(), 'active' ) ) {     replaced by line below for (attempted) commonality with function above
    if ( $product && ! $product->is_purchasable() ) {
        $link = str_replace('class=&quot;button', 'class=&quot;button ActiveSubscription', $link);
    }
    return $link;
}

问题原因分析

  1. 钩子触发范围差异:woocommerce_product_add_to_cart_text在所有生成按钮文本的场景下都会触发,全局$product变量稳定;而woocommerce_loop_add_to_cart_link仅在商品循环(商城列表、分类页)中生效,若某个订阅商品通过自定义模板/短码渲染,该钩子不会执行,导致类无法添加。
  2. 字符串替换的脆弱性:依赖固定的class=&quot;button字符串进行替换,若商品按钮的HTML属性顺序、写法有差异(比如class="button"后紧跟其他类名无空格),替换会失效。
  3. 状态判断逻辑偏差:is_purchasable()的判断规则和“我的账户”页面的活跃订阅判断逻辑可能不一致,部分订阅商品虽显示为活跃,但is_purchasable()返回true,导致新增代码未选中。

解决方案

方案1:统一订阅判断逻辑+安全添加类

使用WooCommerce Subscriptions官方函数判断活跃订阅,同时通过DOM解析安全添加类,避免字符串替换的局限性:

add_filter( 'woocommerce_loop_add_to_cart_link', 'filter_loop_add_to_cart_link', 10, 2 );
function filter_loop_add_to_cart_link( $link, $product ) {
    // 和“我的账户”页面一致的活跃订阅判断
    if ( is_user_logged_in() && wcs_user_has_subscription( get_current_user_id(), $product->get_id(), 'active' ) ) {
        // 解析HTML并添加类
        $dom = new DOMDocument();
        @$dom->loadHTML(mb_convert_encoding($link, 'HTML-ENTITIES', 'UTF-8'));
        $aTags = $dom->getElementsByTagName('a');
        foreach ($aTags as $tag) {
            $classes = $tag->hasAttribute('class') ? explode(' ', $tag->getAttribute('class')) : [];
            $classes[] = 'ActiveSubscription';
            $tag->setAttribute('class', implode(' ', array_unique($classes)));
        }
        $link = $dom->saveHTML($dom->getElementsByTagName('p')->item(0));
    }
    return $link;
}

方案2:同步原文本修改的判断逻辑

如果要和原按钮文本修改逻辑完全对齐,保留is_purchasable()判断,同时改用DOM解析添加类:

add_filter( 'woocommerce_loop_add_to_cart_link', 'custom_add_to_cart_link_with_class', 10, 2 );
function custom_add_to_cart_link_with_class( $link, $product ) {
    if ( $product && ! $product->is_purchasable() ) {
        $dom = new DOMDocument();
        @$dom->loadHTML(mb_convert_encoding($link, 'HTML-ENTITIES', 'UTF-8'));
        $aTags = $dom->getElementsByTagName('a');
        foreach ($aTags as $tag) {
            $current_classes = $tag->getAttribute('class');
            $tag->setAttribute('class', trim($current_classes . ' ActiveSubscription'));
        }
        $link = $dom->saveHTML($dom->getElementsByTagName('p')->item(0));
    }
    return $link;
}

方案3:排查未匹配商品的状态

对未被选中的那个商品做单独检查:

  • 查看商品编辑页的库存、购买权限设置,确认是否真的!is_purchasable();
  • 检查该商品的按钮是否通过woocommerce_loop_add_to_cart_link钩子生成,若为自定义模板输出,需单独添加类的逻辑。

内容的提问来源于stack exchange,提问作者user801347

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 22:04:54