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

如何通过独立单行输入字段构建PHP数组并实现地址验证

Gravity Forms独立地址字段验证解决方案

问题分析

原代码针对Gravity Forms内置复合地址字段做验证,但当前表单使用独立单行文本字段存储地址、城市、州、邮编,需要调整字段取值方式和验证钩子,同时复用原有的Google Geocoding验证逻辑。


1. 获取独立字段值的正确方式

对于Gravity Forms的独立单行文本字段,有两种可靠的取值方式:

  • 使用Gravity Forms提供的rgpost()函数(安全处理POST数据,推荐):格式为rgpost('input_{字段ID}'),比如字段ID为5,就用rgpost('input_5')获取提交值。
  • 直接从$_POST数组获取:$_POST['input_{字段ID}'],但rgpost()会自动处理空值和转义,更安全。

你可以通过Gravity Forms表单编辑器查看每个字段的ID(编辑字段时,右侧面板会显示“字段ID”),或者通过浏览器检查元素,#field_{ID}中的数字就是字段ID。


2. 收集字段值并传入验证函数

使用Gravity Forms的全局表单验证钩子gform_validation,在表单提交时统一收集所有地址相关字段的值,封装后传入验证逻辑,最后根据验证结果设置表单错误。

修改后的完整代码

/**
 * 核心地址验证逻辑:复用原Google Geocoding验证逻辑
 * @param string $street1 地址行1
 * @param string $street2 地址行2(可选)
 * @param string $city 城市
 * @param string $state 州/省份
 * @param string $zip 邮编
 * @return array ['is_valid' => bool, 'message' => string]
 */
function validate_address_with_google($street1, $street2, $city, $state, $zip) {
    $result = ['is_valid' => true, 'message' => ''];
    
    // 检查必填字段是否为空
    $required_inputs = [
        'street1' => $street1,
        'city' => $city,
        'state' => $state,
        'zip' => $zip
    ];
    $empty_input = false;
    foreach ($required_inputs as $name => $value) {
        if (empty(trim($value))) {
            $empty_input = true;
            break;
        }
    }
    if ($empty_input) {
        return [
            'is_valid' => false,
            'message' => '请填写完整的地址信息:街道、城市、州/省份和邮编。'
        ];
    }

    // 清理字段值:去除首尾空格,合并多空格为单空格
    $street1 = preg_replace('/^\s+|\s+$|\s+(?=\s)/', '', $street1);
    $street2 = preg_replace('/^\s+|\s+$|\s+(?=\s)/', '', $street2);
    $city = preg_replace('/^\s+|\s+$|\s+(?=\s)/', '', $city);
    $state = preg_replace('/^\s+|\s+$|\s+(?=\s)/', '', $state);
    $zip = preg_replace('/^\s+|\s+$|\s+(?=\s)/', '', $zip);

    // 检查地址行1是否包含街道号和街道名
    if (!str_contains($street1, " ")) {
        return [
            'is_valid' => false,
            'message' => '地址格式不正确,请在地址行1中填写街道号和街道名(例如:123 Main St)。'
        ];
    }
    $streetnumber = substr($street1, 0, strpos($street1, " ", 0));
    $streetname = substr($street1, strpos($street1, " ", 0) + 1);

    // 拼接完整地址
    $street = !empty($street2) ? "{$street1}, {$street2}" : $street1;
    $full_address = "{$street}, {$city}, {$state} {$zip}";

    // 调用Google Geocoding API
    $api_key = "YOUR_GOOGLE_GEOCODING_API_KEY"; // 替换为你的API密钥
    $url = "https://maps.google.com/maps/api/geocode/json?key=" . rawurlencode($api_key) . "&address=" . rawurlencode($full_address);
    
    GFCommon::log_debug(__METHOD__ . "(): 调用API地址:{$url}");
    $resp_json = file_get_contents($url);
    if (!$resp_json) {
        GFCommon::log_debug(__METHOD__ . "(): API请求失败");
        return [
            'is_valid' => false,
            'message' => '地址验证失败,请稍后重试。'
        ];
    }

    $resp = json_decode($resp_json, true);
    if ($resp['status'] !== 'OK') {
        GFCommon::log_debug(__METHOD__ . "(): API返回状态:{$resp['status']}");
        return [
            'is_valid' => false,
            'message' => '这不是一个有效的地址,请检查后重新填写。'
        ];
    }

    // 解析API返回的地址组件
    $valid_input = true;
    $resp_data = [
        'street_number_short' => '',
        'street_number_long' => '',
        'street_name_short' => '',
        'street_name_long' => '',
        'city_short' => '',
        'city_long' => '',
        'state_short' => '',
        'state_long' => '',
        'zip_short' => '',
        'zip_long' => ''
    ];

    foreach ($resp['results'][0]['address_components'] as $comp) {
        if (in_array("street_number", $comp['types'])) {
            $resp_data['street_number_short'] = $comp['short_name'];
            $resp_data['street_number_long'] = $comp['long_name'];
        }
        if (in_array("route", $comp['types'])) {
            $resp_data['street_name_short'] = $comp['short_name'];
            $resp_data['street_name_long'] = $comp['long_name'];
        }
        if (in_array("locality", $comp['types'])) {
            $resp_data['city_short'] = $comp['short_name'];
            $resp_data['city_long'] = $comp['long_name'];
        }
        if (in_array("administrative_area_level_1", $comp['types'])) {
            $resp_data['state_short'] = $comp['short_name'];
            $resp_data['state_long'] = $comp['long_name'];
        }
        if (in_array("postal_code", $comp['types'])) {
            $resp_data['zip_short'] = $comp['short_name'];
            $resp_data['zip_long'] = $comp['long_name'];
        }
    }

    // 验证地址组件匹配度
    if (!in_array($streetnumber, [$resp_data['street_number_short'], $resp_data['street_number_long']])) {
        $valid_input = false;
    }
    if (!in_array($state, [$resp_data['state_short'], $resp_data['state_long']])) {
        $valid_input = false;
    }
    if (!in_array($zip, [$resp_data['zip_short'], $resp_data['zip_long']])) {
        $valid_input = false;
    }

    // 生成错误信息或确认有效
    if (!$valid_input) {
        $suggested_address = "{$resp_data['street_number_long']} {$resp_data['street_name_long']}, {$resp_data['city_long']}, {$resp_data['state_long']} {$resp_data['zip_long']}";
        $message = empty($resp_data['street_number_long']) ? '这不是一个有效的地址,请检查后重新填写。' : "这不是一个有效的地址,您是否指的是:<br>{$suggested_address}";
        return ['is_valid' => false, 'message' => $message];
    }

    return $result;
}

/**
 * Gravity Forms全局表单验证钩子:收集独立字段值并调用验证逻辑
 * 替换{FORM_ID}为你的实际表单ID(比如原代码中的8)
 */
add_filter('gform_validation_{FORM_ID}', 'custom_independent_address_validation');
function custom_independent_address_validation($validation_result) {
    $form = $validation_result['form'];
    GFCommon::log_debug(__METHOD__ . '(): 开始验证独立地址字段');

    // 替换为你的实际字段ID
    $street1_id = 5;   // 地址行1字段ID
    $street2_id = 6;   // 地址行2字段ID(可选)
    $city_id = 7;      // 城市字段ID
    $state_id = 8;     // 州/省份字段ID
    $zip_id = 9;       // 邮编号段ID

    // 收集字段值
    $street1 = rgpost("input_{$street1_id}");
    $street2 = rgpost("input_{$street2_id}");
    $city = rgpost("input_{$city_id}");
    $state = rgpost("input_{$state_id}");
    $zip = rgpost("input_{$zip_id}");

    // 调用核心验证逻辑
    $validation = validate_address_with_google($street1, $street2, $city, $state, $zip);

    if (!$validation['is_valid']) {
        // 设置表单验证失败,并添加错误信息
        $validation_result['is_valid'] = false;
        // 将错误信息关联到地址行1字段,可根据需求修改关联字段
        foreach ($form['fields'] as &$field) {
            if ($field->id == $street1_id) {
                $field->failed_validation = true;
                $field->validation_message = $validation['message'];
                break;
            }
        }
    }

    GFCommon::log_debug(__METHOD__ . '(): 验证完成,结果:' . ($validation['is_valid'] ? '有效' : '无效'));
    $validation_result['form'] = $form;
    return $validation_result;
}

代码使用说明

  1. 替换关键参数:
    • 将{FORM_ID}替换为你的Gravity Forms表单ID(比如原代码中的8)。
    • 替换$street1_id、$street2_id等变量的值为你的实际字段ID。
    • 在validate_address_with_google函数中填入你的Google Geocoding API密钥。
  2. 错误信息关联:代码默认将错误信息显示在地址行1字段下方,你可以修改foreach ($form['fields'] as &$field)部分,将错误关联到其他字段或设置全局表单错误。
  3. 日志调试:Gravity Forms的调试日志可以帮助排查问题,开启后可在表单设置中查看日志内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 00:25:32