You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决WooCommerce结账时自定义textarea值无法存入自定义表问题

WordPress自定义textarea字段值无法保存到自定义数据库表的问题

我在订单创建时尝试将自定义textarea的输入内容写入WordPress自定义表,但cardcontent字段仅存储了一个分号,无法获取到实际输入值。

当前实现流程

  1. 自定义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>
  1. 前端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 );
});
  1. 后端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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 06:00:09