
本文教你如何将两种 woocommerce 按钮文本逻辑(指定商品显示“去结算”,已加入购物车的商品显示“✓ 已选中”)合并到一个健壮的过滤器中,避免冲突并确保兼容性。
在 WooCommerce 主题或子主题的 functions.php 文件中,若同时启用多个针对 woocommerce_product_single_add_to_cart_text 钩子的过滤器(例如:一个用于特定商品定制文案,另一个用于购物车状态判断),极易因执行顺序、重复全局变量调用或逻辑覆盖导致功能失效甚至白屏。正确的做法是将所有业务逻辑收敛至单个函数中,并解耦关键判断逻辑。
以下是经过优化、生产就绪的完整实现方案:
// ✅ 主过滤器:统一控制单产品页“加入购物车”按钮文案
add_filter( 'woocommerce_product_single_add_to_cart_text', 'woo_custom_cart_button_text' );
function woo_custom_cart_button_text() {
$current_product_id = get_the_ID();
// 定义需特殊处理的指定商品 ID 列表(请按需修改)
$special_products = array( 82, 74 );
// 判断当前商品是否已在购物车中
$is_in_cart = is_product_in_cart( $current_product_id );
// 优先级逻辑:先识别是否为指定商品,再结合购物车状态决策文案
if ( in_array( $current_product_id, $special_products ) ) {
// 对指定商品:无论是否已在购物车,始终显示“去结算”
return __( 'go to checkout', 'woocommerce' );
} elseif ( $is_in_cart ) {
// 对普通商品:若已在购物车,则显示“✓ 已选中”
return __( '✓ already selected', 'woocommerce' );
} else {
// 默认状态:显示标准文案
return __( 'Add to Cart', 'woocommerce' );
}
}
// ? 辅助函数:安全检测商品是否存在于购物车(兼容 WC 3.0+)
function is_product_in_cart( $product_id ) {
// 防御性检查:确保购物车已初始化且非空
if ( ! WC()->cart || ! WC()->cart->get_cart_contents_count() ) {
return false;
}
foreach ( WC()->cart->get_cart() as $cart_item ) {
// 使用 strict comparison(===)匹配 product_id(含变体处理)
if ( $cart_item['product_id'] === $product_id ||
( isset( $cart_item['variation_id'] ) && $cart_item['variation_id'] === $product_id ) ) {
return true;
}
}
return false;
}✅ 关键优化说明:
- 逻辑清晰分层:先判断是否为 special_products,再判断是否 in_cart,避免嵌套 if/elseif 的歧义;
- 兼容性增强:使用 WC()->cart 替代已弃用的 $woocommerce->cart(适配 WooCommerce 3.0+);
- 健壮性提升:增加购物车存在性与数量检查,防止空购物车引发警告;
- 变体支持:辅助函数中同时校验 product_id 和 variation_id,确保商品变体也能被正确识别;
- 可维护性强:$special_products 数组集中管理,便于后续增删 ID。
⚠️ 注意事项:
- 请务必将示例中的 array( 82, 74 ) 替换为你实际需要设置“去结算”的商品 ID;
- 若需对分类、标签或自定义字段触发特殊文案,可在主函数中扩展条件判断;
- 修改后建议清除对象缓存(如使用 WP Super Cache 或 Redis),并测试单产品页、购物车页及 AJAX 加购流程;
- 不建议直接在 functions.php 中硬编码大量逻辑——长期项目推荐封装为轻量插件。
通过该方案,你既能保留原有“已加入购物车”状态反馈,又能为高优先级商品(如服务类、订阅类)提供直达结算的 UX 引导,实现语义明确、无冲突、易扩展的按钮文案管理体系。










