小狮网AI学习

通过修改核心文件实现(仅供学习和理解)

以下步骤将直接修改 WooCommerce 的模板文件。请务必在操作前备份你的网站和数据库。

第一步:定位并复制模板文件

WooCommerce 的结账页面字段是通过模板文件生成的。你需要找到并修改这个文件。

  1. 登录你的网站服务器(通过 FTP 或主机面板的文件管理器)。
  2. 导航到以下目录:wp-content/plugins/woocommerce/templates/checkout/
  3. 找到名为 form-billing.php 的文件。这个文件负责生成账单地址区域的所有字段,包括姓名。
  4. form-billing.php 文件复制到你的电脑上,作为备份和编辑用。

第二步:编辑 form-billing.php 文件

用代码编辑器(如 VS Code, Sublime Text 等)打开你复制的 form-billing.php 文件。

  1. 找到姓氏和名字的代码块

在文件中搜索 $fields['billing']['billing_first_name']$fields['billing']['billing_last_name']。你会找到类似下面这样的代码块:

php

<p class="form-row form-row-first validate-required" id="billing_first_name_field">
    <label for="billing_first_name" class="">
        <?php esc_html_e( 'First name', 'woocommerce' ); ?> <span class="required">*</span>
    </label>
    <input type="text" class="input-text" name="billing_first_name" id="billing_first_name" autocomplete="given-name" value="<?php echo esc_attr( $checkout->get_value( 'billing_first_name' ) ); ?>" placeholder="<?php esc_attr_e( 'First name', 'woocommerce' ); ?>">
</p>

<p class="form-row form-row-last validate-required" id="billing_last_name_field">
    <label for="billing_last_name" class="">
        <?php esc_html_e( 'Last name', 'woocommerce' ); ?> <span class="required">*</span>
    </label>
    <input type="text" class="input-text" name="billing_last_name" id="billing_last_name" autocomplete="family-name" value="<?php echo esc_attr( $checkout->get_value( 'billing_last_name' ) ); ?>" placeholder="<?php esc_attr_e( 'Last name', 'woocommerce' ); ?>">
</p>

删除原有代码并替换为新代码

将上面找到的两个 <p>...</p> 代码块完全删除,然后将其替换为下面的代码:

php

  1. <?php // 获取已保存的姓名值,如果存在则合并显示 $full_name = ''; $first_name = $checkout->get_value( 'billing_first_name' ); $last_name = $checkout->get_value( 'billing_last_name' ); if ( ! empty( $first_name ) && ! empty( $last_name ) ) { $full_name = $first_name . ' ' . $last_name; } elseif ( ! empty( $first_name ) ) { $full_name = $first_name; } elseif ( ! empty( $last_name ) ) { $full_name = $last_name; } ?> <p class="form-row form-row-wide validate-required" id="billing_full_name_field"> <label for="billing_full_name" class=""> <?php esc_html_e( 'Full Name', 'woocommerce' ); ?> <span class="required">*</span> </label> <input type="text" class="input-text" name="billing_full_name" id="billing_full_name" value="<?php echo esc_attr( $full_name ); ?>" placeholder="<?php esc_attr_e( 'Enter your full name', 'woocommerce' ); ?>"> </p>代码解释
    • 我们先用 PHP 逻辑获取了 billing_first_namebilling_last_name 的值,并将它们合并成一个 $full_name 变量。这样,如果用户之前填写过信息,表单会自动显示他们的全名。
    • 然后,我们创建了一个新的、宽度为 form-row-wide(整行)的输入框。
    • 这个新输入框的 name 属性是 billing_full_name,我们将在下一步用它来处理数据。

第三步:处理表单提交的数据

现在,前端的输入框合并好了,但当用户提交表单时,WooCommerce 仍然期望收到 billing_first_namebilling_last_name 两个字段。我们需要一个机制,将用户在 billing_full_name 输入框中填写的内容,分割成名和姓,并分别存入对应的数据库字段。

这需要修改另一个核心文件。

  1. 回到服务器上的 WooCommerce 插件目录:

wp-content/plugins/woocommerce/

导航到 includes/class-wc-checkout.php 文件。这个文件是处理结账流程的核心类。

备份此文件! 这个文件非常重要。

打开 class-wc-checkout.php 并找到 process_checkout() 方法。这个方法非常长。

process_checkout() 方法内部,找到处理 $_POST 数据的地方。通常在方法的开头部分,你会看到类似 $posted_data = $this->get_posted_data(); 的代码。

$posted_data = $this->get_posted_data();之后,添加以下代码:

php

  1. // Custom code to split full name into first and last name if ( isset( $_POST['billing_full_name'] ) && ! empty( $_POST['billing_full_name'] ) ) { $full_name = sanitize_text_field( $_POST['billing_full_name'] ); // Split the name into parts. This will split on the last space. $name_parts = preg_split( '/\s+(?=\S*+$)/', $full_name ); if ( ! empty( $name_parts ) ) { $first_name = $name_parts[0]; $last_name = isset( $name_parts[1] ) ? $name_parts[1] : ''; // Update the posted data so WooCommerce uses our split values $_POST['billing_first_name'] = $first_name; $_POST['billing_last_name'] = $last_name; // Also update the $posted_data array in case it's used later $posted_data['billing_first_name'] = $first_name; $posted_data['billing_last_name'] = $last_name; } }代码解释
    • 我们首先检查 billing_full_name 是否存在于提交的数据中。
    • 使用正则表达式 preg_split( '/\s+(?=\S*+$)/', $full_name ) 来分割字符串。这个正则表达式会在最后一个空格处分割,这样可以正确处理中间有空格的名字(例如 “Van der Sar” 会被当作姓)。
    • 然后,我们将分割后的第一部分作为 billing_first_name,剩余部分(如果有)作为 billing_last_name
    • 最后,我们手动更新了 $_POST 全局变量和 $posted_data 数组,将分割好的名和姓放回去。这样,后续的 WooCommerce 处理流程就会无缝地接收到它所期望的数据格式。

第四步:上传修改后的文件

  1. 将你修改过的 form-billing.php 文件上传回服务器的 wp-content/plugins/woocommerce/templates/checkout/ 目录,覆盖原始文件。
  2. 将你修改过的 class-wc-checkout.php 文件上传回服务器的 wp-content/plugins/woocommerce/includes/ 目录,覆盖原始文件。

完成以上步骤后,刷新你的结账页面,你应该就能看到合并后的 “姓名” 输入框了。提交订单后,你可以在 WordPress 后台的订单详情中检查,姓名是否被正确地分割并保存。


✅ 安全、推荐的实现方法(自定义插件)

为了让你的修改永久生效,我们应该使用 WooCommerce 提供的钩子(Hooks)系统。下面是创建一个简单自定义插件的完整代码。

  1. wp-content/plugins/ 目录下,创建一个新文件夹,命名为 wc-merge-name-fields
  2. 在该文件夹内,创建一个新文件,命名为 wc-merge-name-fields.php
  3. 将以下代码完整地复制并粘贴到 wc-merge-name-fields.php 文件中:

php

<?php
/*
Plugin Name: WooCommerce Merge Name Fields
Plugin URI: https://yourwebsite.com/
Description: Merges the first and last name fields into a single full name field on the WooCommerce checkout page.
Version: 1.0
Author: Your Name
Author URI: https://yourwebsite.com/
License: GPL2
*/

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

// Check if WooCommerce is active
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {

    /**
     * Step 1: Remove the default first and last name fields
     */
    function wc_remove_default_name_fields( $fields ) {
        unset( $fields['billing']['billing_first_name'] );
        unset( $fields['billing']['billing_last_name'] );
        return $fields;
    }
    add_filter( 'woocommerce_billing_fields', 'wc_remove_default_name_fields' );

    /**
     * Step 2: Add the custom full name field
     */
    function wc_add_custom_full_name_field( $fields ) {
        $fields['billing']['billing_full_name'] = array(
            'label'       => __( 'Full Name', 'woocommerce' ),
            'placeholder' => _x( 'Enter your full name', 'placeholder', 'woocommerce' ),
            'required'    => true,
            'class'       => array( 'form-row-wide' ),
            'clear'       => true,
            'priority'    => 20, // Position it where the original name fields were
        );
        return $fields;
    }
    add_filter( 'woocommerce_billing_fields', 'wc_add_custom_full_name_field' );

    /**
     * Step 3: Process the custom field data
     */
    function wc_process_custom_name_field_data( $order_id, $posted_data, $order ) {
        if ( isset( $_POST['billing_full_name'] ) && ! empty( $_POST['billing_full_name'] ) ) {
            $full_name = sanitize_text_field( $_POST['billing_full_name'] );
            
            // Split the name into parts (split on the last space)
            $name_parts = preg_split( '/\s+(?=\S*+$)/', $full_name );
            
            if ( ! empty( $name_parts ) ) {
                $first_name = $name_parts[0];
                $last_name = isset( $name_parts[1] ) ? $name_parts[1] : '';
                
                // Update the order meta data
                update_post_meta( $order_id, '_billing_first_name', $first_name );
                update_post_meta( $order_id, '_billing_last_name', $last_name );
                
                // Also update the user meta if the user is logged in
                if ( get_current_user_id() ) {
                    update_user_meta( get_current_user_id(), 'billing_first_name', $first_name );
                    update_user_meta( get_current_user_id(), 'billing_last_name', $last_name );
                }
            }
        }
    }
    add_action( 'woocommerce_checkout_update_order_meta', 'wc_process_custom_name_field_data', 10, 3 );

    /**
     * Step 4: Display the full name correctly in admin order details
     */
    function wc_admin_order_display_full_name( $order ) {
        $first_name = get_post_meta( $order->get_id(), '_billing_first_name', true );
        $last_name  = get_post_meta( $order->get_id(), '_billing_last_name', true );
        
        if ( $first_name || $last_name ) {
            echo '<p><strong>' . __( 'Billing Name:', 'woocommerce' ) . '</strong> ' . esc_html( $first_name . ' ' . $last_name ) . '</p>';
        }
    }
    // Remove the default billing name display
    remove_action( 'woocommerce_admin_order_data_after_billing_address', 'woocommerce_admin_order_display_billing_address', 10 );
    // Add our custom billing name display
    add_action( 'woocommerce_admin_order_data_after_billing_address', 'wc_admin_order_display_full_name', 10 );

}
  1. 保存文件后,登录到你的 WordPress 后台,导航到 “插件” > “已安装插件”,你会看到 “WooCommerce Merge Name Fields” 这个新插件。点击 “启用” 即可。

现在,你的结账页面姓名输入框已经安全地合并了,并且这个修改不会因为 WooCommerce 的升级而丢失。这才是在 WordPress 生态中进行开发的正确方式。

评论

《“小狮网AI学习”》 有 1 条评论

  1. 一位 WordPress 评论者 的头像

    您好,这是一条评论。若需要审核、编辑或删除评论,请访问仪表盘的评论界面。评论者头像来自 Gravatar

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注