torann/laravel-weather
Torann's Laravel Weather package brings current conditions and forecasts into Laravel through a simple facade and configurable API providers. It supports caching and multiple weather services, making it easy to add weather data to any Laravel app.
Architecture fit. The package's model — a Weather facade over pluggable, config-selected drivers — is a textbook adapter abstraction, and it fits a Laravel 5.5+ app that needs weather data without committing to a vendor. The important architectural move, though, is not adopting the package as-is; it's wrapping it behind our own WeatherProvider port with our own DTO, cache decorator, and fallback chain. That reframing makes the package disposable, which is the correct posture for a 33-star, zero-dependent dependency. The facade unifies calling conventions but not payloads, so the abstraction is thinner than it looks.
Integration feasibility. Installation is trivial (composer require, auto-discovery on 5.5+, publish config). The real gate is the day-one viability audit. Several bundled drivers are dead or gated: Yahoo Weather retired, Weather Underground's public API shut down, OpenWeatherMap's older endpoints deprecated in favor of One Call 3.0 (paid). Expect one workable driver at most. If that driver is the one we'd call directly anyway, the package buys us an afternoon and should be sequenced as a throwaway spike, not a production dependency. That is a business decision, not a technical one, and should be made explicitly before we spend a sprint.
Technical risk. Elevated and concentrated in three places: (1) upstream health — small maintainer, drift between versions, README not authoritative; (2) resilience — no timeouts, retries, or circuit breaker, so an unresponsive provider becomes an unresponsive page; (3) silent failure — misconfigured drivers return empty arrays rather than errors, unit drift between drivers is invisible, and null temperatures can flow into number_format(). The saving grace is the small surface and permissive BSD-2-Clause license, which makes a fork a two-hour task instead of a two-day one — provided we've written the one-page doc listing methods and response keys we depend on.
Key questions.
composer.json PHP and illuminate/support constraints match our Laravel version?src/ and writing a ~50-line One Call 3.0 client ourselves?Stack fit. Strong for a Laravel monolith or service already using facades. Weak if we already have established HTTP client conventions — a direct client gives us control over timeouts, retries, and response mapping without an extra abstraction layer.
Migration path. Largely greenfield; there is little to migrate from beyond ad-hoc vendor calls. Recommended sequence: (1) one-day spike with a live key to confirm a working driver and document the response shape (dump raw output in tinker first); (2) define our WeatherProvider port and normalize into our DTO on the way in; (3) bind the package adapter behind the port; (4) wrap it in a cache decorator keyed on driver + units + rounded coordinates (~2 dp); (5) add a shallow fallback chain (max two providers) behind the port; (6) add a null object so empty forecasts render "unavailable," not 0°C; (7) add a scheduled contract test that hits the live provider hourly; (8) add an out-of-band cache-warming job for displayed locations. Never call Weather:: from controllers or Blade.
Compatibility. Pin the dependency immediately (1.0.*) — no surprise composer update should swap driver behavior under us. Ensure adapter code reads driver, units, and TTL via config(), never env(), and validate with php artisan config:cache locally. Treat the published config/weather.php as ours; diff it against the vendor file on upgrade. Watch for the generic Weather facade alias colliding with other packages — alias explicitly if so.
Sequencing. The spike is the decision gate. If it confirms the surviving driver is one we'd call directly, we stop here and write the thin client; the package isn't earning its keep. If it confirms genuine abstraction value, proceed through port → adapter → cache → fallback → null object → contract test → warm cache, each as an independently shippable increment. Decide the fork plan in advance: vendor src/, keep the same port, publish an internal one-pager listing the exact methods and response keys we depend on.
Maintenance. We own it in practice. Assume upstream will go quiet. Budget for periodic vendor-config diffing after upgrades (published config drift is a real source of "why did production stop reading the new driver"). The internal fork doc is the entire insurance policy — write it during integration, not after the first incident.
Support. There is no vendor support. Support = internal on-call plus fork capability. The hourly contract test is our only early-warning system for provider payload changes; the package will not surface them. Log raw payloads behind a debug flag for the first two weeks to distinguish "provider lied" from "we mapped it wrong."
Scaling. Weather calls are HTTP; the package does not batch or cache intelligently on our behalf. Rendering a list of 40 locations via per-row Weather::getCurrent() is 40 sequential requests — batch through our cache or precompute in a job. The cache decorator is not optional: full-precision coordinate keys give a near-100% miss rate and a quota bill, while rounding to 2 dp gives sensible locality. Warm the top-N displayed locations out of band; let long-tail locations go cold to bound spend. Guard against cache stampede on expiry with Cache::lock() or refresh-ahead.
Failure modes to expect and instrument for.
0°C. Mitigate with the null object and an alert on null-object fallthrough rate.fromRaw() and unit-test against a known fixture.Location value object; assert index 0 of a daily forecast is our tomorrow.Ramp-up. Technically small — the config file is the real documentation, and reading one driver class is the fastest path to understanding the surface. The real ramp-up risk is organizational: teams must agree (a) not to call the facade directly, (b) to go through the port, and (c) to accept the DTO normalization discipline. That is a one-hour conversation and a code-review checklist, not a training program. The cost of skipping it is that the package becomes load-bearing in product code and the fork escape hatch quietly closes.
How can I help you explore Laravel packages today?