A PHP 8.4 METAR weather report parser. Parses raw METAR strings into structured, readonly value objects with full remark support and human-readable labels.
composer require jamesmorrison/metarRequires PHP 8.4 or higher.
use JamesMorrison\Metar\Parser;
$metar = new Parser('METAR EGLL 141250Z 24015G25KT 9999 FEW040CB 12/08 Q1015 NOSIG');Every component is a readonly value object with typed properties and a label() method:
$metar->station->icao; // 'EGLL'
$metar->observationTime->day; // 14
$metar->observationTime->hour; // 12
$metar->observationTime->minute; // 50
$metar->wind->direction; // 240
$metar->wind->speed; // 15
$metar->wind->gusts; // 25
$metar->wind->unit; // WindUnit::Knots
$metar->wind->speedKnots; // 15.0
$metar->wind->speedMps; // 7.7
$metar->visibility->distance; // 9999.0
$metar->visibility->unit; // VisibilityUnit::Metres
$metar->clouds[0]->amount; // CloudAmount::Few
$metar->clouds[0]->height; // 4000
$metar->clouds[0]->type; // CloudType::Cumulonimbus
$metar->temperature->temperature; // 12
$metar->temperature->dewpoint; // 8
$metar->pressure->hectopascals; // 1015.0
$metar->pressure->inchesOfMercury; // 29.97All components implement Labelable and Stringable:
$metar->wind->label(); // 'Wind from 240 degrees at 15 knots gusting 25 knots'
$metar->pressure->label(); // '1015 hPa / 29.97 inHg'
echo $metar->temperature; // 'Temperature 12°C (54°F), dewpoint 8°C (46°F)'
// Full METAR summary
echo $metar->label();The parser implements JsonSerializable:
json_encode($metar, JSON_PRETTY_PRINT);When CAVOK is reported, visibility/weather/clouds are not parsed:
$metar = new Parser('METAR EGLL 141250Z 24015KT CAVOK 12/08 Q1015');
$metar->cavok; // true| Property | Type | Description |
|---|---|---|
station |
?Station |
ICAO station identifier |
observationTime |
?ObservationTime |
Day, hour, and minute (UTC) |
modifiers |
Modifier[] |
AUTO, COR, etc. |
wind |
?Wind |
Direction, speed, gusts, unit (with dual-unit conversions) |
windVariation |
?WindVariation |
Variable wind direction range |
visibility |
?Visibility |
Prevailing visibility (with dual-unit conversions) |
directionalVisibility |
DirectionalVisibility[] |
Sector-specific visibility |
runwayVisualRange |
RunwayVisualRange[] |
RVR per runway |
weather |
Weather[] |
Present weather phenomena |
clouds |
Cloud[] |
Cloud layers |
temperature |
?Temperature |
Temperature and dewpoint (Celsius + Fahrenheit) |
pressure |
?Pressure |
Altimeter setting (hPa + inHg) |
windShear |
?WindShear |
Wind shear warnings |
recentWeather |
RecentWeather[] |
Recent weather phenomena |
trends |
Trend[] |
NOSIG, TEMPO, BECMG trends |
remarks |
?Remarks |
Decoded remark groups |
cavok |
bool |
Ceiling and visibility OK |
The parser decodes 25+ remark types including:
- Station type (AO1/AO2)
- Sea-level pressure
- Peak wind and wind shift
- Hourly temperature / temperature extremes
- Pressure tendency and rapid pressure change
- Precipitation (hourly, 3/6-hour, 24-hour)
- Lightning (frequency, type, direction)
- Weather events (beginning/ending times)
- Variable ceiling and visibility
- Significant clouds (CB, TCU, ACC, etc.)
- Virga, obscurations, snow depth/increase
- Sensor status and maintenance indicators
$metar = new Parser('METAR KJFK 141250Z 24015KT 10SM FEW040 12/08 A2997 RMK AO2 SLP153 T01170083');
foreach ($metar->remarks->groups as $remark) {
echo $remark->label() . "\n";
}composer pest # Run tests
composer analyse # PHPStan (max level)
composer pint # Code style
composer test # All of the aboveMIT