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.0RC1(1mo ago)1103BSD-2-ClausePHPPHP ^8.1

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 2w ago

READMEChangelog (2)Dependencies (20)Versions (30)Used By (0)

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

[](#hordeservice_weather)

Weather-service abstraction for PHP 8.1+ with a modern PSR-4 API and a set of ready-made providers.

`3.0.0` ships both the modern API under `Horde\Service\Weather\` and the legacy PSR-0 API under `Horde_Service_Weather*`. New code should target the modern API. Legacy classes are only provided to technically not break old users. A lot of functionality in the legacy code base targets dead API versions or providers. Every user is encouraged to migrate to the new API immediately.

Providers
---------

[](#providers)

ProviderAPI keyCoverageNotesOpen-MeteononeGlobalFree, no registration. Recommended for testing and demo useOpenWeatherMaprequiredGlobalCommercial. Free tier 1000 calls/day on `/data/2.5` endpointsWeatherAPI.comrequiredGlobalCommercial. Free tier 1M calls/month includes air quality, astronomy, location searchUS NWS (`api.weather.gov`)noneUS onlyCustom `User-Agent` required per NWS termsMETAR (`aviationweather.gov`)noneGlobal aviation stationsICAO-keyed. Custom `User-Agent` requestedInstallation
------------

[](#installation)

```
composer require horde/service_weather
```

Quick start
-----------

[](#quick-start)

Every provider takes a PSR-18 HTTP client plus a PSR-17 request factory. `horde/http` ships both (`Horde\Http\Client\Curl` and `Horde\Http\Client\Mock` implement `Psr\Http\Client\ClientInterface`; `Horde\Http\RequestFactory` implements `Psr\Http\Message\RequestFactoryInterface`). Guzzle, Symfony HttpClient, and every other modern PHP HTTP library also implement PSR-18 / PSR-17 and drop in directly.

```
use Horde\Http\Client\Curl;
use Horde\Http\Options;
use Horde\Http\RequestFactory;
use Horde\Http\ResponseFactory;
use Horde\Http\StreamFactory;
use Horde\Service\Weather\Weather;
use Horde\Service\Weather\ValueObject\Location;

$responseFactory = new ResponseFactory();
$streamFactory = new StreamFactory();
$http = new Curl($responseFactory, $streamFactory, new Options());

$weather = Weather::openMeteo($http, new RequestFactory());
$current = $weather->getCurrentWeather(Location::fromCoordinates(52.52, 13.41));
echo $current->temperature->toCelsius();
echo $current->condition->getDescription();
```

Using Guzzle instead is a one-line swap:

```
$http = new \GuzzleHttp\Client();
$requestFactory = new \Http\Factory\Guzzle\RequestFactory();
$weather = Weather::openMeteo($http, $requestFactory);
```

API key providers
-----------------

[](#api-key-providers)

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

$rf = new RequestFactory();

$weather = Weather::openWeatherMap($http, $rf, 'your-owm-key');
// or
$weather = Weather::weatherApi($http, $rf, 'your-weatherapi-key');

$forecast = $weather->getForecast(
    Location::fromCoordinates(40.7128, -74.0060),
    days: 5,
);
foreach ($forecast as $period) {
    printf(
        "%s: %d°C / %d°C - %s\n",
        $period->date->format('Y-m-d'),
        $period->highTemperature?->toCelsius() ?? 0,
        $period->lowTemperature?->toCelsius() ?? 0,
        $period->condition->getDescription(),
    );
}
```

Capability interfaces
---------------------

[](#capability-interfaces)

Providers implement a small core interface plus optional capability interfaces. Callers `instanceof`-check for optional features:

```
use Horde\Service\Weather\AirQualityProvider;
use Horde\Service\Weather\AstronomyProvider;
use Horde\Service\Weather\HourlyForecast;
use Horde\Service\Weather\StationLookup;

$provider = $weather->getProvider();

if ($provider instanceof HourlyForecast) {
    $hourly = $provider->getHourlyForecast($location, hours: 24);
}
if ($provider instanceof AirQualityProvider) {
    $aq = $provider->getAirQuality($location);
    echo $aq->getCategory()?->value;  // "moderate", "good", ...
}
if ($provider instanceof AstronomyProvider) {
    $astro = $provider->getAstronomy($location);
    echo $astro->sunset?->format('H:i');
}
if ($provider instanceof StationLookup) {
    $station = $provider->getStation('KJFK');
}
```

Full interface list:

- `WeatherProvider` (core)
- `ForecastCapabilities` – describe supported forecast lengths
- `HourlyForecast` – intra-day granularity
- `LocationSearch` – free-form location resolution (WeatherAPI only at 3.0)
- `StationLookup` – observation stations (NWS, METAR)
- `AirQualityProvider` – PM/gas concentrations and locale AQIs
- `AstronomyProvider` – sun/moon rise, set, phase
- `AlertProvider` – weather alerts. Version `3.0.0` only provides an interface and provider implementations may follow in a `3.x` minor (see [doc/FEATURE\_GAPS.md](doc/FEATURE_GAPS.md))

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

[](#configuration)

`WeatherConfig` collects optional knobs: API key, units, language, timeout, cache lifetime, PSR-16 cache instance, custom User-Agent. It's immutable. Use the `with*()` methods to derive new configs.

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

$config = WeatherConfig::default()
    ->withUnits(Units::IMPERIAL)
    ->withLanguage('de')
    ->withUserAgent('my-app/1.0 (+https://example.com)')
    ->withCache($psr16Cache)
    ->withCacheLifetime(900);

$weather = Weather::nationalWeatherService($http, new RequestFactory(), $config);
```

Caching
-------

[](#caching)

When a PSR-16 cache is set on `WeatherConfig`, provider HTTP calls are transparently deduplicated. The cache key is derived from the request URI. TTL is `cacheLifetime`. To enable caching, pass a `ResponseFactory` and `StreamFactory` alongside the config so the decorator can rebuild PSR-7 responses from the cached tuples.

```
use Horde\Http\ResponseFactory;
use Horde\Http\StreamFactory;
use Horde\Service\Weather\Weather;
use Horde\Service\Weather\ValueObject\WeatherConfig;

$config = WeatherConfig::default()->withCache($psr16Cache);
$weather = Weather::openMeteo(
    $http,
    $rf,
    $config,
    new ResponseFactory(),
    new StreamFactory(),
);

$weather->getCurrentWeather($location);  // hits HTTP
$weather->getCurrentWeather($location);  // hits cache
```

Non-2xx responses and exceptions are never cached.

Legacy `Horde_Service_Weather*` API
-----------------------------------

[](#legacy-horde_service_weather-api)

Legacy code that still uses the PSR-0 classes continues to work at `3.x`:

```
$weather = Horde_Service_Weather::factory('Owm', [
    'apikey' => 'your-key',
    'http_client' => new Horde_Http_Client(),
]);
$conditions = $weather->getCurrentConditions('boston,ma');
```

Every legacy class is `@deprecated`-tagged in its docblock. See [doc/UPGRADING.md](doc/UPGRADING.md) for migration notes covering each in-tree consumer (timeobjects driver, base weather blocks) and the constant / method-name mapping between old and new APIs.

Feature gaps
------------

[](#feature-gaps)

Not every legacy feature is ported yet and some 2026-standard weather-API features are not (yet) exposed. Notable items include weather alerts (interface only at `3.0.0`), provider attribution metadata, meteorological helpers (wind-chill, dewpoint, humidity derivations) and air-quality forecasts.

See [doc/FEATURE\_GAPS.md](doc/FEATURE_GAPS.md) for the full inventory, categorized as regressions vs features we never had but modern integrators expect.

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

[](#requirements)

- PHP 8.1 or later (readonly properties, enums, named arguments)
- `psr/http-client: ^1` (PSR-18)
- `psr/http-factory: ^1` (PSR-17)
- `psr/http-message: ^1 || ^2` (PSR-7)
- `psr/simple-cache: ^3`
- A caller-supplied PSR-18 client and PSR-17 request factory. `horde/http` (suggested, not required) ships both.

License
-------

[](#license)

BSD-2-Clause. See [LICENSE](LICENSE).

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance92

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community21

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 62.5% 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 ~177 days

Recently: every ~491 days

Total

26

Last Release

38d ago

Major Versions

2.5.5 → 3.0.0alpha22021-02-24

2.5.6 → v3.0.0alpha52026-03-07

PHP version history (6 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.0alpha2PHP ^7

v3.0.0alpha5PHP ^7.4 || ^8

v3.0.0RC1PHP ^8.1

### 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)")[![ralflang](https://avatars.githubusercontent.com/u/646976?v=4)](https://github.com/ralflang "ralflang (23 commits)")[![slusarz](https://avatars.githubusercontent.com/u/381003?v=4)](https://github.com/slusarz "slusarz (20 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

593.7k80](/packages/horde-horde)[horde/kronolith

Calendar and scheduling application

101.9k6](/packages/horde-kronolith)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

86337.5k](/packages/flow-php-flow)[cakephp/cakephp

The CakePHP framework

8.9k20.0M1.9k](/packages/cakephp-cakephp)[tempest/framework

The PHP framework that gets out of your way.

2.3k37.6k21](/packages/tempest-framework)[horde/imp

Webmail application

261.5k](/packages/horde-imp)

PHPackages © 2026

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