PHPackages                             horde/service\_weather - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. horde/service\_weather

ActiveHorde-library[Utility &amp; Helpers](/categories/utility)

horde/service\_weather
======================

Weather service library

v3.0.0alpha5(3mo ago)193BSD-2-ClausePHPPHP ^7.4 || ^8

Since May 21Pushed 1mo ago5 watchersCompare

[ Source](https://github.com/horde/Service_Weather)[ Packagist](https://packagist.org/packages/horde/service_weather)[ Docs](https://www.horde.org/libraries/Horde_Service_Weather)[ RSS](/packages/horde-service-weather/feed)WikiDiscussions FRAMEWORK\_6\_0 Synced today

READMEChangelog (1)Dependencies (11)Versions (28)Used By (0)

Horde Service\_Weather
======================

[](#horde-service_weather)

Modern weather service library for PHP 8.1+ with support for multiple weather providers.

Features
--------

[](#features)

- ✅ **Multiple Providers**: Open-Meteo, OpenWeatherMap, WeatherAPI.com, US National Weather Service
- ✅ **PSR-4 Architecture**: Modern, autoloadable namespace structure
- ✅ **Type Safety**: Full PHP 8.1+ type declarations and readonly properties
- ✅ **Immutable Value Objects**: Temperature, Speed, Pressure with automatic unit conversion
- ✅ **No API Key Required**: Use Open-Meteo or NWS without registration
- ✅ **Standardized Data**: All providers return consistent domain objects
- ✅ **HTTP via horde/http**: PSR-7/18 compatible HTTP client
- ✅ **Backward Compatible**: Legacy PSR-0 providers still work (METAR, WWO, Wunderground)

Installation
------------

[](#installation)

```
composer require horde/service-weather
```

Quick Start
-----------

[](#quick-start)

### Open-Meteo (No API Key Required)

[](#open-meteo-no-api-key-required)

```
use Horde\Service\Weather\Weather;

// Create service using Open-Meteo (free, unlimited, no API key)
$weather = Weather::openMeteo();

// Get current weather for Boston
$current = $weather->getCurrentWeather('42.3601,-71.0589');

echo "Temperature: " . $current->temperature->toCelsius() . "°C\n";
echo "Condition: " . $current->condition->getDescription() . "\n";
echo "Humidity: " . $current->humidity->format() . "\n";

// Get 5-day forecast
$forecast = $weather->getForecast('42.3601,-71.0589', days: 5);

foreach ($forecast->getPeriods() as $period) {
    echo $period->date->format('Y-m-d') . ": ";
    echo $period->condition->getDescription() . " ";
    echo "High: " . $period->highTemperature->toFahrenheit() . "°F ";
    echo "Low: " . $period->lowTemperature->toFahrenheit() . "°F\n";
}
```

### OpenWeatherMap

[](#openweathermap)

```
// Requires API key from https://openweathermap.org/api
// Free tier: 1000 calls/day
$weather = Weather::openWeatherMap('your-api-key-here');

$current = $weather->getCurrentWeather('40.7128,-74.0060'); // New York
```

### WeatherAPI.com

[](#weatherapicom)

```
// Requires API key from https://www.weatherapi.com/
// Free tier: 1 million calls/month
$weather = Weather::weatherApi('your-api-key-here');

$forecast = $weather->getForecast('51.5074,-0.1278', days: 7); // London
```

### US National Weather Service

[](#us-national-weather-service)

```
// No API key required, US locations only
$weather = Weather::nationalWeatherService();

$current = $weather->getCurrentWeather('47.6062,-122.3321'); // Seattle
```

Using Location Objects
----------------------

[](#using-location-objects)

```
use Horde\Service\Weather\ValueObject\Location;

// From coordinates
$location = Location::fromCoordinates(48.8566, 2.3522);

// From coordinate object
$coordinate = Coordinate::fromLatLon(51.5074, -0.1278);
$location = Location::fromCoordinate($coordinate);

// From city name (some providers support this)
$location = Location::fromCity('Paris', 'France');

// Use with weather service
$current = $weather->getCurrentWeather($location);
```

Unit Conversions
----------------

[](#unit-conversions)

All value objects support automatic unit conversion:

### Temperature

[](#temperature)

```
$temp = Temperature::fromCelsius(20);
echo $temp->toCelsius();     // 20.0
echo $temp->toFahrenheit();  // 68.0
echo $temp->toKelvin();      // 293.2
echo $temp->format(Units::IMPERIAL); // "68.0°F"
```

### Wind Speed

[](#wind-speed)

```
$speed = Speed::fromMetersPerSecond(10);
echo $speed->toMetersPerSecond();      // 10.0
echo $speed->toKilometersPerHour();    // 36.0
echo $speed->toMilesPerHour();         // 22.4
echo $speed->toKnots();                // 19.4
```

### Pressure

[](#pressure)

```
$pressure = Pressure::fromMillibars(1013.25);
echo $pressure->getMillibars();        // 1013.3
echo $pressure->getHectopascals();     // 1013.3 (same as millibars)
echo $pressure->getInchesOfMercury();  // 29.92
```

Configuration
-------------

[](#configuration)

Customize provider behavior with `WeatherConfig`:

```
use Horde\Service\Weather\ValueObject\WeatherConfig;
use Horde\Service\Weather\ValueObject\Units;

$config = WeatherConfig::default()
    ->withUnits(Units::IMPERIAL)      // Use Fahrenheit, mph, inHg
    ->withLanguage('es')               // Spanish translations
    ->withTimeout(15)                  // 15 second HTTP timeout
    ->withCacheLifetime(600);          // Cache for 10 minutes

$weather = Weather::openMeteo(config: $config);
```

Provider Comparison
-------------------

[](#provider-comparison)

ProviderFree TierAPI KeyCoverageCurrentForecast**Open-Meteo**UnlimitedNoGlobal✅✅ 16-day**OpenWeatherMap**1K/dayYesGlobal✅✅ 5-day**WeatherAPI.com**1M/monthYesGlobal✅✅ 14-day**NWS**UnlimitedNoUS only✅✅ 7-dayDomain Objects
--------------

[](#domain-objects)

### CurrentWeather

[](#currentweather)

```
$current = $weather->getCurrentWeather($location);

// Always available
$current->location;           // Location object
$current->temperature;        // Temperature object
$current->condition;          // WeatherCondition enum
$current->observationTime;    // DateTimeImmutable

// Often available (provider-dependent)
$current->feelsLike;          // Temperature|null
$current->humidity;           // Humidity|null
$current->pressure;           // Pressure|null
$current->wind;               // Wind|null
$current->visibility;         // float|null (km)
$current->cloudCover;         // int|null (0-100%)
$current->uvIndex;            // float|null
```

### Forecast

[](#forecast)

```
$forecast = $weather->getForecast($location, days: 5);

$forecast->getLocation();      // Location object
$forecast->getPeriodsCount();  // int
$forecast->getPeriods();       // array
$forecast->getPeriod(0);       // ForecastPeriod|null
```

### ForecastPeriod

[](#forecastperiod)

```
foreach ($forecast->getPeriods() as $period) {
    $period->date;                    // DateTimeImmutable
    $period->temperature;             // Temperature (average)
    $period->condition;               // WeatherCondition
    $period->highTemperature;         // Temperature|null
    $period->lowTemperature;          // Temperature|null
    $period->humidity;                // Humidity|null
    $period->pressure;                // Pressure|null
    $period->wind;                    // Wind|null
    $period->precipitationProbability; // float|null (0.0-1.0)
    $period->precipitationAmount;     // float|null (mm)
    $period->cloudCover;              // int|null (0-100%)
}
```

Weather Conditions
------------------

[](#weather-conditions)

Standardized conditions across all providers:

```
enum WeatherCondition {
    CLEAR, PARTLY_CLOUDY, CLOUDY, OVERCAST,
    FOG, DRIZZLE, RAIN, FREEZING_RAIN,
    SNOW, SLEET, THUNDERSTORM, HAIL,
    TORNADO, HURRICANE, UNKNOWN
}

$condition = WeatherCondition::RAIN;
echo $condition->getDescription();  // "Rain"
echo $condition->getIconCode();     // "10"
```

Error Handling
--------------

[](#error-handling)

```
use Horde\Service\Weather\Exception\ApiException;
use Horde\Service\Weather\Exception\InvalidApiKeyException;
use Horde\Service\Weather\Exception\InvalidLocationException;

try {
    $current = $weather->getCurrentWeather($location);
} catch (InvalidApiKeyException $e) {
    // API key is invalid or missing
} catch (InvalidLocationException $e) {
    // Location format is invalid
} catch (ApiException $e) {
    // General API error (network, rate limit, etc.)
}
```

Advanced Usage
--------------

[](#advanced-usage)

### Custom HTTP Client

[](#custom-http-client)

```
use Horde\Http\Client;

$httpClient = new Client([
    'timeout' => 30,
    'userAgent' => 'MyApp/1.0',
]);

$weather = Weather::openMeteo($httpClient);
```

### Direct Provider Access

[](#direct-provider-access)

```
use Horde\Service\Weather\Provider\OpenMeteo;
use Horde\Http\Client;
use Horde\Service\Weather\ValueObject\WeatherConfig;

$provider = new OpenMeteo(
    new Client(),
    WeatherConfig::default()->withUnits(Units::IMPERIAL)
);

$current = $provider->getCurrentWeather('42.3601,-71.0589');
```

Legacy PSR-0 Support
--------------------

[](#legacy-psr-0-support)

The legacy PSR-0 API (Horde\_Service\_Weather) is still available for backward compatibility:

```
// Old PSR-0 API (still works)
$weather = Horde_Service_Weather::factory('Metar', [
    'metar_path' => '/path/to/metar/files'
]);
```

Upgrading from PSR-0 (Horde 5)
------------------------------

[](#upgrading-from-psr-0-horde-5)

Migrating from the legacy `Horde_Service_Weather` API? See **[doc/UPGRADING.md](doc/UPGRADING.md)** for a complete migration guide including:

- Side-by-side code comparisons
- Provider migration paths
- Common patterns and gotchas
- Testing strategies
- Troubleshooting tips

**Quick example:**

```
// Before (PSR-0)
$weather = Horde_Service_Weather::factory('Owm', ['apikey' => 'key']);
$conditions = $weather->getCurrentConditions('boston,ma');
echo $conditions->temp . "°F";

// After (PSR-4)
$weather = Weather::openWeatherMap('key');
$current = $weather->getCurrentWeather('42.3601,-71.0589');
echo $current->temperature->toFahrenheit() . "°F";
```

Testing
-------

[](#testing)

```
# Run all tests
vendor/bin/phpunit

# Run only PSR-4 tests
vendor/bin/phpunit test/unit/

# Run only legacy PSR-0 tests
vendor/bin/phpunit test/Horde/
```

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- horde/http
- horde/date
- horde/exception
- horde/translation
- horde/url

License
-------

[](#license)

BSD License. See LICENSE file for details.

Links
-----

[](#links)

- **Documentation**:
- **Repository**: [https://github.com/horde/Service\_Weather](https://github.com/horde/Service_Weather)
- **Provider APIs**:
    - [Open-Meteo](https://open-meteo.com/)
    - [OpenWeatherMap](https://openweathermap.org/api)
    - [WeatherAPI.com](https://www.weatherapi.com/)
    - [US National Weather Service](https://www.weather.gov/documentation/services-web-api)

Contributing
------------

[](#contributing)

Contributions are welcome! Please follow the Horde coding standards and include tests for new features.

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance85

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community21

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 63% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~180 days

Recently: every ~459 days

Total

25

Last Release

119d ago

Major Versions

2.5.5 → 3.0.0alpha12021-02-24

2.5.6 → v3.0.0alpha52026-03-07

PHP version history (5 changes)2.1.1PHP &gt;=5.3.0,&lt;=6.0.0alpha1

2.3.2PHP &gt;=5.3.0,&lt;=8.0.0alpha1

2.5.5PHP ^5.3 || ^7

3.0.0alpha1PHP ^7

v3.0.0alpha5PHP ^7.4 || ^8

### Community

Maintainers

![](https://www.gravatar.com/avatar/c943a083635c28520599075eaea7ede2d743b7697b76e84d6bdc37e52cc8249b?d=identicon)[yunosh](/maintainers/yunosh)

![](https://www.gravatar.com/avatar/c931cd02664859360478593450d6c473a05bb12b209dfacfc534cd13257cc7ef?d=identicon)[ralflang](/maintainers/ralflang)

![](https://www.gravatar.com/avatar/e4f6c6771993db2ed500959b42353f6cf6a2ca0406d9617f7ae680f4504faa4a?d=identicon)[horde](/maintainers/horde)

![](https://www.gravatar.com/avatar/a7767adb66b45f2f05bcd44d49bc4e67efacd9ce05b161ce2d481d5dd6af025c?d=identicon)[mrubinsk](/maintainers/mrubinsk)

![](https://www.gravatar.com/avatar/816e2b926f25f8cd2939054c7a7173011b4303d690e25ab61bf33cf8c7cf71ae?d=identicon)[tdannhauer](/maintainers/tdannhauer)

---

Top Contributors

[![mrubinsk](https://avatars.githubusercontent.com/u/66822?v=4)](https://github.com/mrubinsk "mrubinsk (390 commits)")[![yunosh](https://avatars.githubusercontent.com/u/379318?v=4)](https://github.com/yunosh "yunosh (187 commits)")[![slusarz](https://avatars.githubusercontent.com/u/381003?v=4)](https://github.com/slusarz "slusarz (20 commits)")[![ralflang](https://avatars.githubusercontent.com/u/646976?v=4)](https://github.com/ralflang "ralflang (18 commits)")[![renan](https://avatars.githubusercontent.com/u/28046?v=4)](https://github.com/renan "renan (2 commits)")[![thomasjfox](https://avatars.githubusercontent.com/u/1146758?v=4)](https://github.com/thomasjfox "thomasjfox (1 commits)")[![remicollet](https://avatars.githubusercontent.com/u/270445?v=4)](https://github.com/remicollet "remicollet (1 commits)")

### Embed Badge

![Health badge](/badges/horde-service-weather/health.svg)

```
[![Health](https://phpackages.com/badges/horde-service-weather/health.svg)](https://phpackages.com/packages/horde-service-weather)
```

###  Alternatives

[horde/horde

Horde base application

583.0k70](/packages/horde-horde)[horde/kronolith

Calendar and scheduling application

101.5k4](/packages/horde-kronolith)[horde/imp

Webmail application

261.3k](/packages/horde-imp)[horde/imap_client

IMAP client library

275.5k19](/packages/horde-imap-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
