nwidart/laravel-forecast
Laravel Forecast is a weather forecast package for Laravel by Nicolas Widart. It fetches current conditions and multi-day forecasts from pluggable providers, with a clean API, caching, and config for quickly adding weather data to any Laravel app.
The package is a thin Laravel wrapper around forecast-php: it gives you a config file, a container binding, and a convenient entry point for issuing forecast requests, while the underlying client does the HTTP work.
composer require <vendor>/<package>
php artisan vendor:publish --tag=config
config/forecast.php. As of 2.1 this is the primary integration surface — options no longer need to be repeated on every call.First use case to validate the install: make a single request from php artisan tinker with no inline options at all. If it returns data using only the config values, your 2.1 setup is correct. Only after that works should you start layering per-request options on top.
Look first at the published config file, then at the client class the container binds — that class is where the forecast-php hand-off happens, and it is the file you will most often need to read when behaviour surprises you.
Config-first, override-second. Treat the config file as the source of truth for anything stable across the application: API credentials, default units, language/locale, timeouts, and any provider-level options. Reach for per-request options only when the value genuinely varies at runtime — a user's preferred unit, a different location granularity, a one-off extended forecast.
Wrap it in your own service. Do not let controllers or Blade templates call the forecast client directly. Introduce a small ForecastService (or a repository) that depends on the package's client, applies your domain defaults, and returns a DTO. This is the single most valuable pattern here: it isolates you from the 2.1 dependency swap and any future one, and it gives you one obvious place to add caching.
Cache aggressively. Forecast data is a near-perfect cache candidate — expensive upstream, tolerant of staleness, and keyed by a small tuple of location and options. Cache the normalised result, not the raw response, and build the cache key from the effective option set (config defaults merged with overrides), otherwise two callers with different units will collide.
Push non-interactive work to the queue. Anything that fetches forecasts for many locations — warming a dashboard, refreshing a set of cities — belongs in a job. The config-driven options travel with the job for free, which is exactly the payoff of the 2.1 change: a job no longer needs to carry an options array through its constructor.
Test against your wrapper, not the client. Fake your ForecastService in feature tests. For the handful of tests that must exercise the real client integration, bind a stubbed HTTP handler and assert on the outgoing request rather than on the parsed response.
Re-run config:cache after upgrading to 2.1. The most common post-upgrade symptom will be "my options are ignored." Options set in config are read at boot; a stale cached config will silently keep serving the old (per-request) behaviour. php artisan config:clear first, then re-cache.
The forecast-php swap is quietly breaking for extenders. If you type-hinted the previous HTTP client, extended it, or mocked it in tests by class name, that code breaks on 2.1 with no deprecation period. Audit for any reference to the old class before upgrading. If you followed the wrapper pattern above, the blast radius is one file.
Know the precedence order. Config defaults should be merged under per-request options, never the reverse. Verify this yourself on 2.1 with a deliberate conflict — set a unit in config, override it in a call — because a silent inversion here produces plausible-looking but wrong output.
Watch for option leakage between calls. If the client is bound as a singleton and per-request options mutate its state, one call can contaminate the next within the same request lifecycle (and in Octane, across requests). Prefer passing options per call and letting the client compose them, or bind as a scoped instance.
Debug the outgoing request, not the response. When a call returns unexpected data, log the effective option set and the resolved URL/query before it goes out. Most bugs here are a wrong default in config or a merge that dropped a key, not a parsing problem.
Extension point: the container binding is the sanctioned seam. Override it in a service provider to substitute your own client subclass or a decorated version when you need cross-cutting behaviour — retries, logging, metrics — without forking the package.
How can I help you explore Laravel packages today?