如何修改Woocommerce购物车中已存在的预订商品元数据?
修改WooCommerce购物车中预订商品的Duration和End Date
我之前也碰到过类似的问题,核心是没摸透WooCommerce预订对象的更新逻辑和钩子执行时机——咱们一步步来解决你的困扰:
首先,你原来的代码有几个容易踩坑的点:没有同步更新购物车项、没关联duration和end_date的依赖关系,还缺少循环调用防护。下面是修正后的完整方案:
修正后的代码实现
add_action( 'woocommerce_before_calculate_totals', 'update_booking_cart_item_metadata', 20, 1 ); function update_booking_cart_item_metadata( $cart ) { // 防止calculate_totals()触发钩子循环调用 if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) { return; } // 替换成你的实际条件判断逻辑 $my_condition = true; $my_new_duration = 3; // 示例:设置为3天(注意和商品的时长单位匹配) if ( $my_condition ) { foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) { // 确保当前项是有效的预订商品 if ( isset( $cart_item['booking'] ) && is_a( $cart_item['booking'], 'WC_Booking' ) ) { $booking = $cart_item['booking']; // 设置新的时长 $booking->set_duration( $my_new_duration ); // 手动计算并更新结束日期(修改duration后不会自动同步end_date) $start_date = $booking->get_start_date( 'Y-m-d H:i:s' ); $end_date = wc_booking_calculate_end_date( $start_date, $booking->get_duration_unit(), $my_new_duration ); $booking->set_end_date( $end_date ); // 保存预订对象的更改 $booking->save(); // 将更新后的预订对象写回购物车数组 $cart->cart_contents[ $cart_item_key ]['booking'] = $booking; } } // 强制重新计算购物车总计,确保更改生效 $cart->calculate_totals(); } }
关键细节说明
- 钩子优先级:设为20,确保我们的代码在WooCommerce默认购物车计算逻辑之后执行,避免被默认操作覆盖。
- 循环防护:添加
did_action判断,防止calculate_totals()再次触发钩子导致无限循环。 - 类型校验:用
is_a()确认$cart_item['booking']是WC_Booking对象,避免对无效数据操作。 - 同步end_date:修改duration后必须手动计算并设置end_date——这是很多人踩坑的点,WooCommerce预订不会自动根据新时长更新结束日期。
- 更新购物车:修改后的预订对象要重新赋值回购物车数组,否则更改不会被持久化到购物车中。
额外排查建议
- 先把
$my_condition临时设为true测试,排除条件不满足导致的修改不触发问题。 - 检查预订商品的时长单位(比如是“天”还是“小时”),确保
$my_new_duration的单位和商品设置一致,否则end_date计算会出错。 - 开启WooCommerce调试模式(在wp-config.php中设置
WP_DEBUG = true),查看错误日志,能快速定位隐藏的问题。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

