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

如何通过WooCommerce插件重写结账页面的配送与账单地址区块

重写WooCommerce结账地址区块的纯PHP稳定方案

针对本国特殊地址格式需求,以下是完全基于WooCommerce官方PHP钩子的解决方案,不依赖DOM元素,避免JS方案的兼容性问题,且不受用户使用的主题影响:

1. 替换账单地址区块

通过移除WooCommerce默认的账单地址输出动作,替换为自定义的地址表单渲染逻辑:

// 移除默认账单地址输出
remove_action('woocommerce_checkout_billing', 'woocommerce_checkout_billing');
// 添加自定义账单地址输出
add_action('woocommerce_checkout_billing', 'custom_woocommerce_checkout_billing');

function custom_woocommerce_checkout_billing() {
    $checkout = WC()->checkout;
    
    ?>
    <div id="customer_details">
        <div class="col-1">
            <h3><?php esc_html_e('Billing Details', 'your-plugin-text-domain'); ?></h3>
            <div class="woocommerce-billing-fields">
                <?php do_action('woocommerce_before_billing_fields', $checkout); ?>
                
                <!-- 自定义账单地址字段,按本国格式排列 -->
                <p class="form-row form-row-wide">
                    <label for="billing_full_name"><?php esc_html_e('Full Name', 'your-plugin-text-domain'); ?> <span class="required">*</span></label>
                    <input type="text" class="input-text" name="billing_full_name" id="billing_full_name" value="<?php echo esc_attr($checkout->get_value('billing_full_name')); ?>" required />
                </p>
                
                <p class="form-row form-row-wide">
                    <label for="billing_address_line1"><?php esc_html_e('Address Line 1', 'your-plugin-text-domain'); ?> <span class="required">*</span></label>
                    <input type="text" class="input-text" name="billing_address_line1" id="billing_address_line1" value="<?php echo esc_attr($checkout->get_value('billing_address_line1')); ?>" required />
                </p>
                
                <p class="form-row form-row-wide">
                    <label for="billing_district"><?php esc_html_e('District', 'your-plugin-text-domain'); ?> <span class="required">*</span></label>
                    <input type="text" class="input-text" name="billing_district" id="billing_district" value="<?php echo esc_attr($checkout->get_value('billing_district')); ?>" required />
                </p>
                
                <p class="form-row form-row-wide">
                    <label for="billing_postcode"><?php esc_html_e('Postcode', 'your-plugin-text-domain'); ?> <span class="required">*</span></label>
                    <input type="text" class="input-text" name="billing_postcode" id="billing_postcode" value="<?php echo esc_attr($checkout->get_value('billing_postcode')); ?>" required />
                </p>
                
                <!-- 保留WooCommerce默认的邮箱、电话字段(按需调整) -->
                <?php
                woocommerce_form_field('billing_email', array(
                    'type' => 'email',
                    'class' => array('form-row-wide'),
                    'label' => __('Email Address', 'your-plugin-text-domain'),
                    'required' => true,
                ), $checkout->get_value('billing_email'));
                
                woocommerce_form_field('billing_phone', array(
                    'type' => 'tel',
                    'class' => array('form-row-wide'),
                    'label' => __('Phone', 'your-plugin-text-domain'),
                    'required' => true,
                ), $checkout->get_value('billing_phone'));
                ?>
                
                <?php do_action('woocommerce_after_billing_fields', $checkout); ?>
            </div>
        </div>
    </div>
    <?php
}

2. 替换配送地址区块

采用与账单地址相同的逻辑,替换配送地址的输出:

// 移除默认配送地址输出
remove_action('woocommerce_checkout_shipping', 'woocommerce_checkout_shipping');
// 添加自定义配送地址输出
add_action('woocommerce_checkout_shipping', 'custom_woocommerce_checkout_shipping');

function custom_woocommerce_checkout_shipping() {
    $checkout = WC()->checkout;
    
    if (!WC()->cart->needs_shipping()) {
        return;
    }
    
    ?>
    <div class="col-2">
        <h3><?php esc_html_e('Shipping Details', 'your-plugin-text-domain'); ?></h3>
        <div class="woocommerce-shipping-fields">
            <?php do_action('woocommerce_before_shipping_fields', $checkout); ?>
            
            <!-- 自定义配送地址字段,按本国格式排列 -->
            <p class="form-row form-row-wide">
                <label for="shipping_full_name"><?php esc_html_e('Full Name', 'your-plugin-text-domain'); ?> <span class="required">*</span></label>
                <input type="text" class="input-text" name="shipping_full_name" id="shipping_full_name" value="<?php echo esc_attr($checkout->get_value('shipping_full_name')); ?>" required />
            </p>
            
            <p class="form-row form-row-wide">
                <label for="shipping_address_line1"><?php esc_html_e('Address Line 1', 'your-plugin-text-domain'); ?> <span class="required">*</span></label>
                <input type="text" class="input-text" name="shipping_address_line1" id="shipping_address_line1" value="<?php echo esc_attr($checkout->get_value('shipping_address_line1')); ?>" required />
            </p>
            
            <p class="form-row form-row-wide">
                <label for="shipping_district"><?php esc_html_e('District', 'your-plugin-text-domain'); ?> <span class="required">*</span></label>
                <input type="text" class="input-text" name="shipping_district" id="shipping_district" value="<?php echo esc_attr($checkout->get_value('shipping_district')); ?>" required />
            </p>
            
            <p class="form-row form-row-wide">
                <label for="shipping_postcode"><?php esc_html_e('Postcode', 'your-plugin-text-domain'); ?> <span class="required">*</span></label>
                <input type="text" class="input-text" name="shipping_postcode" id="shipping_postcode" value="<?php echo esc_attr($checkout->get_value('shipping_postcode')); ?>" required />
            </p>
            
            <?php do_action('woocommerce_after_shipping_fields', $checkout); ?>
        </div>
    </div>
    <?php
}

3. 验证自定义地址字段

确保必填字段在结账时通过验证:

add_action('woocommerce_after_checkout_validation', 'custom_address_fields_validation', 10, 2);

function custom_address_fields_validation($data, $errors) {
    // 验证账单地址字段
    if (empty($data['billing_full_name'])) {
        $errors->add('billing_full_name_error', __('Please enter your full billing name.', 'your-plugin-text-domain'));
    }
    if (empty($data['billing_address_line1'])) {
        $errors->add('billing_address_line1_error', __('Please enter your billing address line 1.', 'your-plugin-text-domain'));
    }
    if (empty($data['billing_district'])) {
        $errors->add('billing_district_error', __('Please enter your billing district.', 'your-plugin-text-domain'));
    }
    if (empty($data['billing_postcode'])) {
        $errors->add('billing_postcode_error', __('Please enter your billing postcode.', 'your-plugin-text-domain'));
    }
    
    // 验证配送地址字段(仅当需要配送时)
    if (WC()->cart->needs_shipping()) {
        if (empty($data['shipping_full_name'])) {
            $errors->add('shipping_full_name_error', __('Please enter your full shipping name.', 'your-plugin-text-domain'));
        }
        if (empty($data['shipping_address_line1'])) {
            $errors->add('shipping_address_line1_error', __('Please enter your shipping address line 1.', 'your-plugin-text-domain'));
        }
        if (empty($data['shipping_district'])) {
            $errors->add('shipping_district_error', __('Please enter your shipping district.', 'your-plugin-text-domain'));
        }
        if (empty($data['shipping_postcode'])) {
            $errors->add('shipping_postcode_error', __('Please enter your shipping postcode.', 'your-plugin-text-domain'));
        }
    }
}

4. 保存地址数据到订单

将自定义字段的值保存到订单的元数据中,并同步到WooCommerce默认的地址字段(确保订单系统兼容):

add_action('woocommerce_checkout_create_order', 'custom_address_fields_save', 10, 2);

function custom_address_fields_save($order, $data) {
    // 保存账单地址数据
    $order->set_billing_first_name($data['billing_full_name']);
    $order->set_billing_address_1($data['billing_address_line1']);
    $order->update_meta_data('_billing_district', sanitize_text_field($data['billing_district']));
    $order->set_billing_postcode(sanitize_text_field($data['billing_postcode']));
    
    // 保存配送地址数据
    if (WC()->cart->needs_shipping()) {
        $order->set_shipping_first_name($data['shipping_full_name']);
        $order->set_shipping_address_1($data['shipping_address_line1']);
        $order->update_meta_data('_shipping_district', sanitize_text_field($data['shipping_district']));
        $order->set_shipping_postcode(sanitize_text_field($data['shipping_postcode']));
    }
}

5. 调整订单详情与邮件中的地址显示

确保自定义地址字段在订单页面和邮件中正确展示:

// 修改账单地址格式化输出
add_filter('woocommerce_order_get_formatted_billing_address', 'custom_formatted_billing_address', 10, 2);

function custom_formatted_billing_address($address, $order) {
    $district = $order->get_meta('_billing_district');
    $formatted_address = array(
        $order->get_billing_first_name(),
        $order->get_billing_address_1(),
        $district,
        $order->get_billing_postcode(),
    );
    
    // 过滤空值
    $formatted_address = array_filter($formatted_address);
    
    return implode(', ', $formatted_address);
}

// 修改配送地址格式化输出
add_filter('woocommerce_order_get_formatted_shipping_address', 'custom_formatted_shipping_address', 10, 2);

function custom_formatted_shipping_address($address, $order) {
    if (!$order->needs_shipping()) {
        return $address;
    }
    
    $district = $order->get_meta('_shipping_district');
    $formatted_address = array(
        $order->get_shipping_first_name(),
        $order->get_shipping_address_1(),
        $district,
        $order->get_shipping_postcode(),
    );
    
    // 过滤空值
    $formatted_address = array_filter($formatted_address);
    
    return implode(', ', $formatted_address);
}

注意事项

  • 将上述代码添加到你的插件主文件中,替换your-plugin-text-domain为你的插件文本域,用于国际化支持。
  • 根据本国地址格式,调整字段的数量、名称和排列顺序。
  • 若需要添加更多字段(如省份、城市),可在表单中添加对应输入框,并同步更新验证和保存逻辑。

内容的提问来源于stack exchange,提问作者Daniel Eisenhardt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:17:31