WooCommerce按购物车数量添加参会者自定义结账字段的同步问题
WooCommerce门票购票者信息收集修复方案
问题描述
我们售卖门票时需要收集每位购票者的信息,找到一段代码能根据购物车商品数量生成对应参会者的自定义结账字段,但该代码无法将收集到的信息同步到订单邮件及订单详情中,代码已过时且自行更新未成功,原代码如下:
//Custom WooCommerce Checkout Fields based on Quantity add_action( 'woocommerce_before_order_notes', 'person_details' ); function person_details($checkout) { global $woocommerce; $count = $woocommerce->cart->cart_contents_count; $i = 1; for($k=2; $k<= $count; $k++) { $i++; print ('<h3>Please enter details of attendee '.$i.'</h3>'); woocommerce_form_field( 'cstm_full_name'.$i, array( 'type' => 'text', 'class' => array('my-field-class form-row-wide'), 'label' => __('Full name'), 'placeholder' => __('Enter full name'), ), $checkout->get_value( 'cstm_full_name'.$i )); echo '<div class="clear"></div>'; woocommerce_form_field( 'cstm_phone'.$i, array( 'type' => 'text', 'class' => array('my-field-class form-row-first'), 'label' => __('Phone'), 'placeholder' => __('Enter phone number'), ), $checkout->get_value( 'cstm_phone'.$i )); woocommerce_form_field( 'cstm_email'.$i, array( 'type' => 'email', 'class' => array('my-field-class form-row-last'), 'label' => __('Email address'), 'placeholder' => __('Enter email address'), ), $checkout->get_value( 'cstm_email'.$i )); echo '<div class="clear"></div>'; woocommerce_form_field( 'cstm_address'.$i, array( 'type' => 'textarea', 'class' => array('my-field-class form-row-wide'), 'label' => __('Full address'), 'placeholder' => __('Enter full address'), ), $checkout->get_value( 'cstm_address'.$i )); } } /** * Save value of fields */ add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta'); function customise_checkout_field_update_order_meta($order_id) { global $woocommerce; $count = $woocommerce->cart->cart_contents_count; $i = 1; for($k=2; $k<= $count; $k++) { $i++; if (!empty($_POST['cstm_full_name'.$i])) { update_post_meta($order_id, 'Name of Attendee'.$i, sanitize_text_field($_POST['cstm_full_name'.$i])); } if (!empty($_POST['cstm_phone'.$i])) { update_post_meta($order_id, 'Phone of Attendee'.$i, sanitize_text_field($_POST['cstm_phone'.$i])); } if (!empty($_POST['cstm_email'.$i])) { update_post_meta($order_id, 'Email of Attendee'.$i, sanitize_text_field($_POST['cstm_email'.$i])); } if (!empty($_POST['cstm_address'.$i])) { update_post_meta($order_id, 'Address of Attendee'.$i, sanitize_text_field($_POST['cstm_address'.$i])); } } } /** * Add fields to order emails **/ add_filter('woocommerce_email_order_meta_keys', 'my_custom_checkout_field_order_meta_keys'); function my_custom_checkout_field_order_meta_keys( $keys ) { $i = 1; for($k=2; $k<= 50; $k++) { $i++; $keys[] = 'Name of Attendee'.$i; $keys[] = 'Phone of Attendee'.$i; $keys[] = 'Email of Attendee'.$i; $keys[] = 'Email of Participant '.$i; $keys[] = 'Address of Attendee'.$i; } return $keys; }
修复后的完整代码
// 根据购物车数量生成参会者结账字段 add_action( 'woocommerce_before_order_notes', 'person_details' ); function person_details( $checkout ) { $count = WC()->cart->cart_contents_count; // 从第2位参会者开始生成字段(第1位默认用账单信息) for ( $i = 2; $i <= $count; $i++ ) { echo '<h3>请填写第'.$i.'位参会者信息</h3>'; woocommerce_form_field( 'cstm_full_name'.$i, array( 'type' => 'text', 'class' => array('my-field-class form-row-wide'), 'label' => __('姓名'), 'placeholder' => __('请输入姓名'), ), $checkout->get_value( 'cstm_full_name'.$i ) ); echo '<div class="clear"></div>'; woocommerce_form_field( 'cstm_phone'.$i, array( 'type' => 'text', 'class' => array('my-field-class form-row-first'), 'label' => __('电话'), 'placeholder' => __('请输入电话号码'), ), $checkout->get_value( 'cstm_phone'.$i ) ); woocommerce_form_field( 'cstm_email'.$i, array( 'type' => 'email', 'class' => array('my-field-class form-row-last'), 'label' => __('邮箱'), 'placeholder' => __('请输入邮箱地址'), ), $checkout->get_value( 'cstm_email'.$i ) ); echo '<div class="clear"></div>'; woocommerce_form_field( 'cstm_address'.$i, array( 'type' => 'textarea', 'class' => array('my-field-class form-row-wide'), 'label' => __('地址'), 'placeholder' => __('请输入完整地址'), ), $checkout->get_value( 'cstm_address'.$i ) ); } } // 保存参会者字段到订单元数据 add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta'); function customise_checkout_field_update_order_meta( $order_id ) { $count = WC()->cart->cart_contents_count; for ( $i = 2; $i <= $count; $i++ ) { if ( !empty( $_POST['cstm_full_name'.$i] ) ) { update_post_meta( $order_id, '参会者'.$i.'_姓名', sanitize_text_field( $_POST['cstm_full_name'.$i] ) ); } if ( !empty( $_POST['cstm_phone'.$i] ) ) { update_post_meta( $order_id, '参会者'.$i.'_电话', sanitize_text_field( $_POST['cstm_phone'.$i] ) ); } if ( !empty( $_POST['cstm_email'.$i] ) ) { update_post_meta( $order_id, '参会者'.$i.'_邮箱', sanitize_email( $_POST['cstm_email'.$i] ) ); } if ( !empty( $_POST['cstm_address'.$i] ) ) { update_post_meta( $order_id, '参会者'.$i.'_地址', sanitize_textarea_field( $_POST['cstm_address'.$i] ) ); } } } // 在后台订单详情中显示参会者信息 add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_attendee_info_in_admin_order' ); function display_attendee_info_in_admin_order( $order ) { $order_id = $order->get_id(); $count = $order->get_item_count(); // 获取订单商品总数 echo '<div class="attendee-info">'; echo '<h3>参会者信息</h3>'; for ( $i = 2; $i <= $count; $i++ ) { $name = get_post_meta( $order_id, '参会者'.$i.'_姓名', true ); if ( empty( $name ) ) continue; echo '<p><strong>第'.$i.'位参会者:</strong></p>'; echo '<p>姓名:'.$name.'</p>'; echo '<p>电话:'.get_post_meta( $order_id, '参会者'.$i.'_电话', true ).'</p>'; echo '<p>邮箱:'.get_post_meta( $order_id, '参会者'.$i.'_邮箱', true ).'</p>'; echo '<p>地址:'.get_post_meta( $order_id, '参会者'.$i.'_地址', true ).'</p>'; echo '<hr>'; } echo '</div>'; } // 在前台订单详情中显示参会者信息 add_action( 'woocommerce_order_details_after_order_table', 'display_attendee_info_in_frontend_order' ); function display_attendee_info_in_frontend_order( $order ) { $order_id = $order->get_id(); $count = $order->get_item_count(); echo '<section class="attendee-info">'; echo '<h2>参会者信息</h2>'; for ( $i = 2; $i <= $count; $i++ ) { $name = get_post_meta( $order_id, '参会者'.$i.'_姓名', true ); if ( empty( $name ) ) continue; echo '<div class="attendee-item">'; echo '<h3>第'.$i.'位参会者</h3>'; echo '<p><strong>姓名:</strong>'.$name.'</p>'; echo '<p><strong>电话:</strong>'.get_post_meta( $order_id, '参会者'.$i.'_电话', true ).'</p>'; echo '<p><strong>邮箱:</strong>'.get_post_meta( $order_id, '参会者'.$i.'_邮箱', true ).'</p>'; echo '<p><strong>地址:</strong>'.get_post_meta( $order_id, '参会者'.$i.'_地址', true ).'</p>'; echo '</div>'; } echo '</section>'; } // 在订单邮件中显示参会者信息 add_action( 'woocommerce_email_after_order_table', 'display_attendee_info_in_order_email' ); function display_attendee_info_in_order_email( $order ) { $order_id = $order->get_id(); $count = $order->get_item_count(); echo '<h2>参会者信息</h2>'; for ( $i = 2; $i <= $count; $i++ ) { $name = get_post_meta( $order_id, '参会者'.$i.'_姓名', true ); if ( empty( $name ) ) continue; echo '<p><strong>第'.$i.'位参会者:</strong></p>'; echo '<p>姓名:'.$name.'</p>'; echo '<p>电话:'.get_post_meta( $order_id, '参会者'.$i.'_电话', true ).'</p>'; echo '<p>邮箱:'.get_post_meta( $order_id, '参会者'.$i.'_邮箱', true ).'</p>'; echo '<p>地址:'.get_post_meta( $order_id, '参会者'.$i.'_地址', true ).'</p>'; echo '<br>'; } }
关键修改说明
- 替换过时依赖:用
WC()->cart替代全局$woocommerce对象,符合现代WooCommerce开发规范 - 修复邮件逻辑:移除原代码中不存在的
Email of Participant字段,改用woocommerce_email_after_order_table钩子直接输出参会者信息,避免原过滤器的局限性 - 添加订单详情显示:新增后台和前台订单详情的参会者信息展示逻辑,确保管理员和客户都能看到收集的信息
- 优化数据处理:用
sanitize_email处理邮箱字段,sanitize_textarea_field处理地址字段,数据更安全 - 简化循环逻辑:直接用
$i从2开始计数,避免原代码中$k和$i的混乱逻辑 - 本地化字段标签:将字段标签改为中文,更符合国内用户使用习惯
内容的提问来源于stack exchange,提问作者dimension2am
相关产品推荐
相关产品推荐

