本文目录导读:

我来详细说明PHP项目对接天气查询接口的完整流程,以国内常用的和风天气和OpenWeatherMap为例。
准备工作
选择天气API服务商
- 和风天气 (国内首选):https://dev.heweather.com
- OpenWeatherMap (国际):https://openweathermap.org
- 彩云天气:https://docs.caiyunapp.com
获取API密钥
以和风天气为例:
- 注册账号
- 创建应用获取
API Key - 选择免费版或付费版
PHP对接实现
基础封装类
<?php
class WeatherAPI {
private $apiKey;
private $baseUrl;
public function __construct($apiKey, $service = 'heweather') {
$this->apiKey = $apiKey;
// 根据服务商设置base URL
switch ($service) {
case 'heweather':
$this->baseUrl = 'https://devapi.qweather.com/v7';
break;
case 'openweather':
$this->baseUrl = 'https://api.openweathermap.org/data/2.5';
break;
}
}
/**
* 发送HTTP请求
*/
private function sendRequest($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new Exception('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("HTTP Error: $httpCode");
}
return json_decode($response, true);
}
/**
* 获取实时天气 - 和风天气
*/
public function getCurrentWeather($location) {
$url = $this->baseUrl . "/weather/now?location=$location&key={$this->apiKey}";
return $this->sendRequest($url);
}
/**
* 获取未来3天天气预报 - 和风天气
*/
public function getForecast($location, $days = 3) {
$url = $this->baseUrl . "/weather/3d?location=$location&key={$this->apiKey}";
return $this->sendRequest($url);
}
/**
* 获取实时天气 - OpenWeatherMap
*/
public function getCurrentWeatherOWM($location) {
$url = $this->baseUrl . "/weather?q=$location&appid={$this->apiKey}&units=metric&lang=zh_cn";
return $this->sendRequest($url);
}
}
使用示例
<?php
// 1. 基础使用 - 获取实时天气
try {
$weather = new WeatherAPI('YOUR_API_KEY_HERE', 'heweather');
$result = $weather->getCurrentWeather('101010100'); // 北京城市ID
if ($result['code'] === '200') {
$now = $result['now'];
echo "当前温度:{$now['temp']}°C\n";
echo "天气状况:{$now['text']}\n";
echo "风速:{$now['windSpeed']} km/h\n";
echo "湿度:{$now['humidity']}%\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// 2. 通过城市名称查询
function getWeatherByName($cityName) {
// 先获取城市ID (和风天气需要)
$geoUrl = "https://geoapi.qweather.com/v2/city/lookup";
$geoUrl .= "?location=$cityName&key=YOUR_API_KEY";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $geoUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$geoResponse = json_decode(curl_exec($ch), true);
curl_close($ch);
if (!empty($geoResponse['location'])) {
$cityId = $geoResponse['location'][0]['id'];
// 使用城市ID查询天气
$weatherAPI = new WeatherAPI('YOUR_API_KEY');
return $weatherAPI->getCurrentWeather($cityId);
}
return null;
}
// 3. 通过IP定位获取天气
function getWeatherByIP() {
$ip = $_SERVER['REMOTE_ADDR'] ?? '8.8.8.8'; // 生产环境使用真实IP
// 使用和风天气的IP定位
$locationUrl = "https://geoapi.qweather.com/v2/ip?key=YOUR_API_KEY&ip=$ip";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $locationUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$location = json_decode(curl_exec($ch), true);
curl_close($ch);
if (!empty($location['location'])) {
$cityId = $location['location'][0]['id'];
$weatherAPI = new WeatherAPI('YOUR_API_KEY');
return $weatherAPI->getCurrentWeather($cityId);
}
return null;
}
进阶功能封装
带缓存的天气预报类
<?php
class WeatherService {
private $api;
private $cacheDir;
private $cacheTime = 1800; // 30分钟缓存
public function __construct($apiKey) {
$this->api = new WeatherAPI($apiKey);
$this->cacheDir = __DIR__ . '/cache/weather/';
if (!is_dir($this->cacheDir)) {
mkdir($this->cacheDir, 0755, true);
}
}
/**
* 获取天气(带缓存)
*/
public function getWeatherWithCache($location) {
$cacheFile = $this->cacheDir . md5($location) . '.json';
// 检查缓存
if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $this->cacheTime) {
return json_decode(file_get_contents($cacheFile), true);
}
// 从API获取数据
$data = $this->api->getCurrentWeather($location);
// 写入缓存
if (!empty($data)) {
file_put_contents($cacheFile, json_encode($data));
}
return $data;
}
/**
* 获取格式化天气报告
*/
public function getWeatherReport($location) {
$data = $this->getWeatherWithCache($location);
if (isset($data['now'])) {
$now = $data['now'];
return [
'temperature' => $now['temp'] . '°C',
'feels_like' => $now['feelsLike'] . '°C',
'condition' => $now['text'],
'wind' => $now['windDir'] . ' ' . $now['windScale'] . '级',
'humidity' => $now['humidity'] . '%',
'update_time' => $data['updateTime']
];
}
return null;
}
}
// 使用示例
$weatherService = new WeatherService('YOUR_API_KEY');
$report = $weatherService->getWeatherReport('101010100');
echo "当前温度:{$report['temperature']}\n";
echo "天气状况:{$report['condition']}\n";
前端展示示例(HTML+JS)
<!-- weather_display.php -->
<!DOCTYPE html>
<html>
<head>天气预报</title>
<style>
.weather-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
margin: 20px;
max-width: 300px;
}
.temperature {
font-size: 48px;
font-weight: bold;
color: #333;
}
.condition {
font-size: 24px;
color: #666;
}
</style>
</head>
<body>
<div id="weather" class="weather-card">
<h2>当前天气</h2>
<div class="temperature" id="temp">--°C</div>
<div class="condition" id="condition">加载中...</div>
</div>
<script>
function updateWeather() {
fetch('api/get_weather.php?city=北京')
.then(response => response.json())
.then(data => {
document.getElementById('temp').textContent =
data.temperature + '°C';
document.getElementById('condition').textContent =
data.condition;
})
.catch(error => {
console.error('获取天气失败:', error);
});
}
// 每30分钟更新一次
updateWeather();
setInterval(updateWeather, 1800000);
</script>
</body>
</html>
PHP API端点
<?php
// api/get_weather.php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
require_once '../WeatherService.php';
try {
$city = $_GET['city'] ?? '北京';
$weatherService = new WeatherService('YOUR_API_KEY');
$report = $weatherService->getWeatherReport($city);
if ($report) {
echo json_encode([
'success' => true,
'temperature' => $report['temperature'],
'condition' => $report['condition'],
'humidity' => $report['humidity'],
'wind' => $report['wind']
]);
} else {
echo json_encode(['success' => false, 'message' => '天气数据获取失败']);
}
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
错误处理和注意事项
错误处理
try {
$weather = new WeatherAPI('YOUR_API_KEY');
$result = $weather->getCurrentWeather('invalid_location');
if ($result['code'] !== '200') {
// 错误处理
switch ($result['code']) {
case '401':
throw new Exception('API密钥无效');
case '403':
throw new Exception('请求被拒绝');
case '404':
throw new Exception('城市不存在');
default:
throw new Exception('未知错误');
}
}
} catch (Exception $e) {
error_log("Weather API Error: " . $e->getMessage());
echo json_encode(['error' => $e->getMessage()]);
}
性能优化建议
// 1. 使用连接池(如Redis缓存)
class WeatherCache {
private $redis;
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function getCachedWeather($location) {
$key = "weather:$location";
$cached = $this->redis->get($key);
if ($cached) {
return json_decode($cached, true);
}
// 从API获取并缓存
$weather = new WeatherAPI('YOUR_API_KEY');
$data = $weather->getCurrentWeather($location);
// 缓存30分钟
$this->redis->setex($key, 1800, json_encode($data));
return $data;
}
}
// 2. 批量查询优化
function batchGetWeather(array $locations) {
$results = [];
foreach ($locations as $location) {
// 使用多线程或curl_multi并行请求
$results[$location] = getWeatherFromAPI($location);
}
return $results;
}
安全注意事项
// 1. API密钥安全存储
// 不要在代码中硬编码API密钥,使用环境变量
$apiKey = getenv('WEATHER_API_KEY');
// 2. 请求频率限制
class RateLimiter {
private $requests = [];
private $limit = 100; // 每分钟100次
public function checkLimit() {
$now = time();
$this->requests = array_filter($this->requests, function($time) use ($now) {
return $time > ($now - 60);
});
if (count($this->requests) >= $this->limit) {
throw new Exception('请求频率超限');
}
$this->requests[] = $now;
}
}
// 3. 输入验证
function validateLocation($location) {
// 只允许字母、数字和中文
if (!preg_match('/^[a-zA-Z0-9\x{4e00}-\x{9fa5}]+$/u', $location)) {
throw new Exception('无效的位置参数');
}
return true;
}
完整项目结构
weather_project/
├── api/
│ └── get_weather.php # API端点
├── classes/
│ ├── WeatherAPI.php # API封装类
│ ├── WeatherService.php # 业务逻辑封装
│ └── WeatherCache.php # 缓存类
├── config/
│ └── config.php # 配置文件
├── templates/
│ └── weather_display.php # 前端模板
├── cache/ # 缓存目录
├── vendor/ # Composer依赖
├── .env # 环境变量
└── index.php # 入口文件
配置文件示例
<?php
// config/config.php
return [
'weather_api' => [
'service' => 'heweather', // heweather, openweather
'api_key' => getenv('WEATHER_API_KEY'),
'cache_time' => 1800, // 缓存时间(秒)
'timeout' => 10, // 请求超时(秒)
'retry_times' => 3, // 重试次数
]
];
对接天气API的关键要点:
- 选择合适的API服务商:国内推荐和风天气,国际推荐OpenWeatherMap
- 实现缓存机制:减少API调用次数,提高响应速度
- 错误处理:完善异常捕获和错误提示
- 性能优化:使用缓存、连接池等技术
- 安全性:保护API密钥,验证用户输入
这样,你就可以在自己的PHP项目中轻松集成天气查询功能了,如果需要其他天气API的对接方式,可以进一步告诉我。