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

如何用正则快速校验经纬度字符串是否合法
直接用正则判断最轻量,适合表单提交前的初步过滤。但要注意:正则只能验证格式,不能保证地理合理性(比如 999.999 语法合法但显然无效)。
纬度范围是 -90.0 到 90.0,经度是 -180.0 到 180.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、-INF、NAN会通过范围判断 -
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。











