
该教程详解为何 hide_payment_gateways_based_on_weight 在 WordPress 后台触发“Call to a member function get_cart_contents_weight() on null”错误,并提供安全、兼容、符合编码规范的修复方案。
该教程详解为何 `hide_payment_gateways_based_on_weight` 在 wordpress 后台触发“call to a member function get_cart_contents_weight() on null”错误,并提供安全、兼容、符合编码规范的修复方案。
在 WooCommerce 开发中,通过 woocommerce_available_payment_gateways 钩子动态隐藏特定支付方式(如货到付款 COD)是常见需求。但若逻辑未充分考虑执行上下文,极易引发致命错误——正如本例所示:前端正常,后台却抛出 CRITICAL Uncaught Error: Call to a member function get_cart_contents_weight() on null。
根本原因在于:WC()->cart 对象仅在前台购物车、结算等用户会话上下文中被初始化;而在 WordPress 后台(包括订单管理、商品编辑等页面),WC()->cart 为 null。原代码使用 is_admin() 判断存在误区——该函数仅检测是否处于 WordPress 管理后台(即 wp-admin/),但 WooCommerce 的结账流程(如 checkout 页面)虽属前台,却可能被 is_admin() 错误排除;更严重的是,它完全无法阻止钩子在后台其他非购物场景(如订单详情页、邮件预览)中执行,此时直接调用 WC()->cart->get_cart_contents_weight() 必然失败。
✅ 正确做法是:精准限定钩子仅在真正需要计算购物车重量的页面生效——即 is_cart() 或 is_checkout()。这两个条件确保 WC()->cart 已就绪且数据有效。
此外,遵循 WPCS(WordPress Coding Standards) 最佳实践,所有控制结构(如 if)必须使用大括号包裹,避免因缩进误导导致的逻辑错误和可维护性问题。
以下是修复后的完整、健壮、可直接部署的代码:
add_filter( 'woocommerce_available_payment_gateways', 'hide_payment_gateways_based_on_weight', 10, 1 );
function hide_payment_gateways_based_on_weight( $available_gateways ) {
// 仅在购物车页或结算页执行逻辑,确保 WC()->cart 可用
if ( is_cart() || is_checkout() ) {
// 安全获取购物车总重量(单位:克)
$total_weight = WC()->cart->get_cart_contents_weight();
// 注意:条件逻辑已修正为 $total_weight >= 2000(原答案中误写为 2000 >= $total_weight)
// 此处按原始需求——重量 ≥ 2000g 时隐藏 COD
if ( $total_weight >= 2000 && isset( $available_gateways['cod'] ) ) {
unset( $available_gateways['cod'] );
}
}
return $available_gateways;
}⚠️ 关键注意事项:
- 勿用 is_admin() 替代页面上下文判断:is_admin() 与 WooCommerce 前台逻辑无直接关联,应始终优先使用 is_cart() / is_checkout() / is_account_page() 等语义化条件函数;
- 始终校验 $available_gateways 键存在性:使用 isset() 避免 unset() 操作不存在的键引发警告;
- 重量单位统一:get_cart_contents_weight() 返回值单位为 克(g),请根据实际业务确认阈值(如 2000g = 2kg);
- 扩展建议:如需支持多币种或多区域规则,可进一步结合 WC()->customer->get_shipping_country() 或自定义字段增强判断逻辑。
此方案彻底规避了后台致命错误,同时提升代码可读性与长期可维护性,是 WooCommerce 条件化支付网关控制的标准实践。

















