解决WooCommerce结账时自定义textarea值无法存入自定义表问题
WordPress自定义textarea字段值无法保存到自定义数据库表的问题
我在订单创建时尝试将自定义textarea的输入内容写入WordPress自定义表,但cardcontent字段仅存储了一个分号,无法获取到实际输入值。
当前实现流程
- 自定义textarea字段代码:
<div id="cardcontent" class="cardcontent old"> <div id="cardcontentwrapper"> <textarea id='heading' name='heading' placeholder='Please enter a title' class='heading' rows="1" cols="50"></textarea><span id="heading-length-left"></span> <textarea id='bodytext' name='bodytext' placeholder='Please enter a message' class='bodytext' rows="1" cols="50"></textarea> </div> </div>
- 前端JS添加到购物车表单的代码:
// 点击加入购物车时触发的钩子 - 将标题和内容输入框复制到购物车表单 wp.hooks.addAction( 'PC.fe.add_to_cart.before', 'your_namespace', function( view ) { // 获取购物车表单 var $cart_form = view.$cart; jQuery( '.mkl_pc_layers .custom-html.active textarea.heading' ).clone().appendTo( $cart_form ); jQuery( '.mkl_pc_layers .custom-html.active textarea.bodytext' ).clone().appendTo( $cart_form ); });
- 后端
functions.php获取值并写入数据库的代码:
// 结账表单提交、订单创建前触发 add_action( 'woocommerce_checkout_update_order_meta', 'cpm_woocommerce_checkout_update', 10, 2 ); function cpm_woocommerce_checkout_update($order_id, $data) { // 尝试通过$_POST获取textarea值 $cardHeading = $_POST['heading']; $cardBody = $_POST['bodytext']; $order = wc_get_order( $order_id ); global $wpdb; $card = $cardHeading . ";" . $cardBody; $timestamp = time(); $id = 1; $table_name = $wpdb->prefix."cards"; $data = array( 'userid' => $id, 'orderid' => $order_id, 'cardcontent' => $card, 'timestamp' => $timestamp, ); $wpdb->insert( $table_name, $data ); }
问题核心
数据库中cardcontent字段仅存储分号,说明$_POST['heading']和$_POST['bodytext']均未获取到用户输入值。
解决办法
1. 修复前端克隆输入框的逻辑
clone()方法默认复制的是原始空textarea,不会携带用户已输入的内容,需要手动赋值:
wp.hooks.addAction( 'PC.fe.add_to_cart.before', 'your_namespace', function( view ) { var $cart_form = view.$cart; // 获取原输入框及用户输入值 var $heading = jQuery( '.mkl_pc_layers .custom-html.active textarea.heading' ); var $bodytext = jQuery( '.mkl_pc_layers .custom-html.active textarea.bodytext' ); // 克隆后赋值并添加到购物车表单 $heading.clone().val($heading.val()).appendTo( $cart_form ); $bodytext.clone().val($bodytext.val()).appendTo( $cart_form ); });
2. 将字段值存入购物车会话
仅添加到表单不足以保留数据,需通过钩子将值存入购物车项元数据:
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_card_data_to_cart', 10, 2 ); function save_custom_card_data_to_cart( $cart_item_data, $product_id ) { // 过滤并保存标题 if( isset( $_POST['heading'] ) ) { $cart_item_data['card_heading'] = sanitize_textarea_field( $_POST['heading'] ); } // 过滤并保存内容 if( isset( $_POST['bodytext'] ) ) { $cart_item_data['card_body'] = sanitize_textarea_field( $_POST['bodytext'] ); } // 添加唯一键确保每个购物车项数据独立 $cart_item_data['unique_key'] = md5( microtime().rand() ); return $cart_item_data; }
3. 从购物车会话读取值并写入数据库
结账时$_POST字段可能丢失,需从订单项元数据中读取:
// 将购物车项数据关联到订单 add_action( 'woocommerce_checkout_create_order_line_item', 'save_card_data_to_order_item', 10, 4 ); function save_card_data_to_order_item( $item, $cart_item_key, $values, $order ) { if( isset( $values['card_heading'] ) ) { $item->add_meta_data( '_card_heading', $values['card_heading'] ); } if( isset( $values['card_body'] ) ) { $item->add_meta_data( '_card_body', $values['card_body'] ); } } // 更新订单元时写入自定义表 add_action( 'woocommerce_checkout_update_order_meta', 'cpm_woocommerce_checkout_update', 10, 2 ); function cpm_woocommerce_checkout_update($order_id, $data) { global $wpdb; $order = wc_get_order( $order_id ); // 从订单项中提取卡片数据 $cardHeading = ''; $cardBody = ''; foreach( $order->get_items() as $item ) { $cardHeading = $item->get_meta( '_card_heading' ) ?: $cardHeading; $cardBody = $item->get_meta( '_card_body' ) ?: $cardBody; } $card = $cardHeading . ";" . $cardBody; $timestamp = time(); $id = get_current_user_id() ?: 1; // 替换为当前用户ID,游客默认1 $table_name = $wpdb->prefix."cards"; $data = array( 'userid' => $id, 'orderid' => $order_id, 'cardcontent' => $card, 'timestamp' => $timestamp, ); $wpdb->insert( $table_name, $data ); }
4. 安全优化
- 用
sanitize_textarea_field()过滤用户输入,防止XSS攻击和非法字符 - 读取
$_POST值时先判断是否存在,避免报错:
$cardHeading = isset( $_POST['heading'] ) ? sanitize_textarea_field( $_POST['heading'] ) : ''; $cardBody = isset( $_POST['bodytext'] ) ? sanitize_textarea_field( $_POST['bodytext'] ) : '';
内容的提问来源于stack exchange,提问作者Jolle
相关产品推荐
相关产品推荐

