php如何判断变量为经纬度数据_php经纬度格式检测法【示例】

5次阅读

正则可快速校验经纬度格式合法性,纬度范围-90.0~90.0、经度-180.0~180.0,小数点后1~6位;但需配合Floatval转换与数值边界判断,防止字符串绕过。

php如何判断变量为经纬度数据_php经纬度格式检测法【示例】

如何用正则快速校验经纬度字符串是否合法

直接用正则判断最轻量,适合表单提交前的初步过滤。但要注意:正则只能验证格式,不能保证地理合理性(比如 999.999 语法合法但显然无效)。

纬度范围是 -90.090.0,经度是 -180.0180.0,且支持带符号、小数点后最多 6 位(常见精度需求):

// 纬度正则(含边界) $latRegex = '/^[-+]?([0-8]?d(.d{1,6})?|90(.0{1,6})?)$/';  // 经度正则(含边界) $lngRegex = '/^[-+]?((1[0-7]d|180)(.d{1,6})?|([0-9]?d(.d{1,6})?))$/';  // 示例检测 $lat = "39.9042"; $lng = "116.4074"; var_dump(preg_match($latRegex, $lat) && preg_match($lngRegex, $lng)); // true
  • 必须用 ^$ 锚定,否则 "abc123.45" 这类也会被误判
  • 小数点后位数建议限制在 1-6 位:太多无实际意义,太少(如只允许 1 位)会拒绝有效数据
  • 不推荐用 d+ 替代具体数字范围,否则无法控制值域(如 190.1 会被 ^-?d+.d+$ 放过)

用 floatval + 范围判断更稳妥的运行时校验

正则之后,务必转为浮点数再做数值边界检查——这是防止字符串绕过(如 "+00000039.9042" 或科学计数法 "3.99042e1")的关键一步。

function isValidLatLon($latStr, $lngStr) {     $lat = floatval($latStr);     $lng = floatval($lngStr);          return is_finite($lat) && is_finite($lng)         && $lat >= -90.0 && $lat <= 90.0         && $lng >= -180.0 && $lng <= 180.0; }  // 注意:floatval("123.45abc") → 123.45,所以仍需前置正则或 trim+is_numeric 防干扰
  • is_finite() 必须加,否则 INF-INFNAN 会通过范围判断
  • floatval() 对空格、前导符号、指数形式兼容性好,比 (float) 强制转换更鲁棒
  • 如果输入可能含单位(如 "39.9042°N"),先用 preg_replace('/[^-d.]+/', '', $str) 清洗

处理常见脏数据:空值、NULL、数组、对象

真实接口或表单中,变量可能是 null、空字符串、数组甚至对象,直接丢给正则或 floatval 会出警告或返回意外值。

立即学习PHP免费学习笔记(深入)”;

// 安全提取和转换 function extractLatLon($data) {     if (!is_array($data)) {         return [null, null];     }     $lat = $data['lat'] ?? $data['latitude'] ?? null;     $lng = $data['lng'] ?? $data['longitude'] ?? null;      // 转字符串再清洗,避免对非标类型调用 floatval 报 Notice     $lat = is_scalar($lat) ? trim((string)$lat) : '';     $lng = is_scalar($lng) ? trim((string)$lng) : '';      return [$lat, $lng]; }
  • 永远假设输入不可信,用 ??is_scalar() 做兜底
  • 不要依赖 isset() 判断数组键存在就安全——isset($arr['lat'])$arr['lat'] = null 返回 false,但该键实际存在且值为 null
  • 若原始数据是 GeoJSON 格式(如 ["lng", "lat"] 数组),注意经纬度顺序是反的,需交换

为什么不用 filter_var(FILTER_VALIDATE_FLOAT)?

filter_var($val, FILTER_VALIDATE_FLOAT) 看似简洁,但有严重缺陷:它只验证是否能转成浮点数,完全不检查值域。例如 filter_var("999.999", FILTER_VALIDATE_FLOAT) 返回 999.999,而这不是合法纬度。

  • 它也无法识别带空格或单位的字符串(" 39.9042 " 可以,但 "39.9042°" 不行)
  • 1e2+123 等格式支持不稳定,不同 php 版本行为可能不一致
  • 没有提供小数位数控制,必须额外用 strlen(strrchr(...)) 拆解判断,反而更复杂

真正要省事又可靠,还是正则 + floatval + 边界检查三步组合——少一个环节都可能漏掉边缘 case。

text=ZqhQzanResources