必须用PHP服务端中转调用高德天气API:用curl(非file_get_contents)发GET请求,传Web服务key、city编码(如110000)、extensions=base/all、output=json;返回JSON无data包裹,需先校验status==='1'再取lives0等字段,并缓存城市编码。

怎么用 PHP 发起高德天气 API 请求
高德天气 API 不支持直接前端调用(会跨域且暴露 key),必须用 PHP 做服务端中转。核心就是 file_get_contents() 或 curl_exec() 发 GET 请求,拼好 URL 和参数就行。
常见错误是直接在浏览器里打开带 key 的 URL 测试——高德会返回 "status":400,"info":"INVALID_USER_KEY",因为没带 origin 头或 IP 未备案(开发时建议先用 curl 测试)。
- 必须传
key(控制台申请的 Web 服务 key,不是 JS SDK key) - 城市编码用
city参数,比如北京是110000,不能传 “北京” 或 “beijing” - 实时天气接口是
https://restapi.amap.com/v3/weather/weatherInfo,加extensions=base;预报用extensions=all - 别漏掉
output=json,否则返回 XML(默认值不是 JSON)
如何解析高德返回的 JSON 并防错
高德返回结构简单,但字段名容易写错:lives 是实时数据数组(注意是复数),forecasts 是预报数组,顶层没有 data 包裹——这点和很多其他 API 不同,直接 json_decode($res, true) 后就可取 $data['lives'][0]['temperature']。
容易踩的坑:没检查 status 就直接取值。高德出错时仍返回 200 状态码,但 status 是 0 或 1(1 才成功),info 字段才告诉你具体错哪了。
立即学习“PHP免费学习笔记(深入)”;
- 务必先判断
isset($data['status']) && $data['status'] === '1' -
lives数组可能为空(比如城市编码错),要加!empty($data['lives'])再取[0] - 温度字段是字符串(如
"23"),不是数字,用前最好(int)转下,避免后续计算出错
为什么用 curl 比 file_get_contents 更稳
file_get_contents() 在部分主机上被禁用(尤其共享虚拟主机),或不支持 ssl 上下文,一请求就报 failed to open stream: Unable to find the socket transport "ssl"。curl 则更可控,还能设超时、重试、User-Agent。
另一个关键点:高德要求请求头带 User-Agent,否则某些环境会拒绝(返回空或 403)。file_get_contents() 默认不发这个头,而 curl 可以显式设置。
- 用
curl_setopt($ch, CURLOPT_TIMEOUT, 5)防止卡死 - 必须加
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP') - 记得
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true),不然直接输出到页面 - 别忘了
curl_close($ch),虽然 PHP 会自动回收,但显式关更稳妥
城市编码怎么查又不硬编码
高德没提供公开的城市编码表 API,但可以靠「输入提示 API」间接获取:用 https://restapi.amap.com/v3/config/district 查行政区划,传 keywords=北京 + subdistrict=1,返回里有 districts 数组,每个项含 adcode(就是你要的 city 编码)和 level(province/city/district)。
别用网上搜到的“城市编码大全”静态列表——有些老数据把深圳写成 440300(正确),但把雄安新区写成不存在的编码,查出来就是空结果。
- 查一级城市(如北京市)用
keywords=北京&subdistrict=1&filter=province - 查二级(如朝阳区)得再进一层,
adcode是上层返回的districts[0]['adcode'] - 缓存查到的
adcode,别每次请求都去查,高德有调用量限制(免费版 1000 次/日)
最麻烦的是用户输“沪”“邕”这种简称,或者“浦东新区”这种功能区——高德的 district 接口对简称支持弱,这时候得 fallback 到搜索 API /v3/config/district?keywords=浦东&subdistrict=2,并检查 level 是否为 district。











