Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Geocoder Laravel Laravel Package

toin0u/geocoder-laravel

Geocoder for Laravel integrates the Geocoder PHP library into Laravel apps, enabling address geocoding and reverse geocoding with configurable providers and caching. Requires PHP 8.2+ and Laravel 11+, with service provider auto-discovery for quick setup.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • The package is a thin Laravel service-provider wrapper around the upstream geocoder-php/Geocoder library. It contributes one container binding (geocoder), one config file, and a fluent query-builder aggregator (ProviderAndDumperAggregator). There is no persistence layer, no schema migration, and no background processing — it is a synchronous, request-scoped outbound HTTP client. Fit is therefore high for any Laravel app that needs address→coordinate, coordinate→address, or IP→locale resolution, and low for apps expecting batch/async geocoding at scale.
  • The dependency chain is the real architectural surface: toin0u/geocoder-laravel → geocoder-php/Geocoder → individual provider packages (google-maps, geoplugin, nominatim, geoip2) → a PSR-18 client. That means the meaningful "integration" work is choosing providers and an adapter, not wiring the package itself.
  • The default HTTP adapter (Geocoder\Laravel\Http\LaravelHttpClient) delegates to Laravel's Http facade. This is a genuine architectural win: Http::fake()/Http::assertSent() work in tests with zero setup, existing global HTTP middleware applies, and timeout/retry/connectTimeout are centrally configurable. It also means geocoding inherits whatever middleware you have registered (logging, tracing, header injection) — usually desirable, occasionally surprising.

Integration feasibility

  • Very low effort to first value: composer require, set GOOGLE_MAPS_API_KEY, and app('geocoder')->geocode('...')->get(). Auto-discovery handles provider registration on modern Laravel; manual provider registration is only relevant pre-5.5.
  • Requirements are PHP ≥ 8.2 and Laravel ≥ 11, which is a hard gate. Any application still on Laravel 10 or PHP 8.1 cannot use current releases and would need to pin an older major (5.x).
  • Config is publishable (vendor:publish --tag=config) and the defaults are sensible but opinionated: a Chain of GoogleMaps then GeoPlugin. That default implies a paid API key and a third-party free service in the request path — both need explicit sign-off.

Technical risk

  • Provider terms of service vs. default cache. The shipped cache duration is effectively permanent (9999999/999999999 seconds, and the README itself is internally inconsistent about which). Google's Geocoding API terms restrict how long results may be cached. A near-forever cache is a compliance exposure that surfaces only at audit or contract review. This is the single highest-severity item in the package's default posture, and it is a policy decision, not a code bug.
  • Boot-time mutation of cache.serializable_classes. Under Laravel 13, the package scans vendor/geocoder-php/* at boot and merges every model class it finds into the app's cache allow-list, narrowly relaxing a security hardening default. The README is commendably explicit about the blast radius and offers an opt-out (auto_register_serializable_classes => false). A TPM should treat this as a security-review item, not an install detail — the correct answer for a regulated environment is likely opt-out plus an explicit allow-list, or doNotCache().
  • Versioning discontinuity. 5.0.0 → 13.0.0 with no intermediate releases, where the major now tracks the Laravel major rather than the Geocoder major. Composer constraints and dependency-upgrade tooling will look alarming on the diff. It is safe, but it costs reviewer time every upgrade.
  • Adapter config is unvalidated. The array form [Class => [args]] forwards arguments straight to the constructor with no signature check ("it's on you to match its signature"). A typo produces a runtime failure at first geocode call, not at boot.
  • Adoption signal is thin. 754 stars is respectable but the dataset reports zero dependents, and the package is effectively a maintained convenience wrapper over the upstream library. The risk is not abandonment — releases are recent and the repo lives under the geocoder-php org — it is that you are one of few consumers exercising the Laravel-specific surface, so obscure bugs may be yours to find.

Key questions

  1. Which provider are we standardizing on, and whose billing account owns the quota? What is peak QPS versus the provider's rate limit?
  2. Does our provider contract permit the cache duration the package defaults to? If not, what is the correct duration, and who owns that config value?
  3. Is boot-time relaxation of cache.serializable_classes acceptable, or do we opt out and maintain an explicit allow-list?
  4. Do we need multi-locale output? Results cache separately per locale, so locale breadth multiplies cache footprint and API spend.
  5. Is a self-hosted path (Nominatim, local GeoIP2 reader) required for privacy, air-gapped environments, or cost control?
  6. What is the intended behavior when geocoding returns an empty collection — silent null, user-facing error, or degraded UI?

Integration Approach

Stack fit

  • Best fit: a Laravel 11/12/13 monolith or API on PHP 8.2+, already using Laravel's Http facade and a Redis cache, with modest geocoding volume (form autocomplete, address normalization, IP-based locale/currency defaults).
  • Poor fit: high-volume batch geocoding, anything needing sub-50ms deterministic latency, air-gapped deployments, or services where a third-party call in the request path is unacceptable.
  • The GeoIP/GeoPlugin half of the default chain is often mistaken for a substitute for proper IP intelligence. For anything beyond coarse country-level inference, evaluate the local GeoIp2 reader (the reader config key exists for exactly this) rather than an external HTTP hop.

Migration path

  • Greenfield: install, publish config, replace the default chain with the provider(s) you have contracted, point cache.store at a dedicated store, ship.
  • From 5.x: the jump to 13.x is a major with behavioral changes — the new default HTTP adapter, the versioning scheme change, and the Laravel 13 cache allow-list behavior. Read the Upgrading section, do not assume semver does the thinking for you. Pinned adapter behavior (Curl\Client, custom CA bundles, proxies) is the most likely regression point.
  • From a bespoke/homegrown geocoder: introduce the package behind an application-level GeocoderService interface so the package's fluent API does not leak into domain code. This also preserves a swap path to a self-hosted provider later.

Compatibility

  • Hard floors: PHP 8.2, Laravel 11. Verify transitive provider packages against your composer.lock before merging.
  • Laravel 13 requires the cache.serializable_classes decision described above. On Laravel 11/12 this is a non-issue, so the decision can be deferred — but it should be made once, not rediscovered during the framework upgrade.
  • The default adapter expects the Http facade; apps that have replaced or wrapped the HTTP layer should confirm the PSR-18 delegation still resolves.

Sequencing

  1. Spike: one controller, one real API key, geocode + reverse + locale against a handful of representative inputs, including garbage inputs.
  2. Provider and contract decision: pick providers, confirm ToS and caching rights, set cache-duration accordingly.
  3. Cache topology: dedicated Redis store (separate database index) so geocode cache churn cannot evict application cache; verify eviction policy.
  4. Config hardening: pin adapter explicitly with timeout/connectTimeout/retry; decide auto_register_serializable_classes.
  5. Application wrapper: normalize the Collection<Address> return into a domain DTO; decide the empty-result contract.
  6. Test harness: Http::fake() fixtures for each provider, asserted in CI so upstream response shape changes fail loudly.
  7. Observability and cost: per-provider call counts, cache hit ratio, error rate, spend alert.
  8. Only then: replace any ad-hoc geocoding call sites.

Operational Impact

Maintenance

  • Low ongoing code maintenance — the package is small and the upstream org is active, with recent releases and a changelog. The maintenance burden is almost entirely config and provider maintenance: API key rotation, provider deprecations, quota changes, and locale/region semantics (the README's note that Google uses TLDs for region values is a classic source of silent wrong results).
  • The major-version realignment means a Laravel upgrade now implies a geocoder-package major bump. Build that into framework upgrade runbooks.
  • Documentation quality is above average (explicit upgrade warnings, explicit security callouts), with one notable defect: the stated default cache duration disagrees between prose and code sample. Treat the config file as the source of truth.

Support

  • The package itself is a thin shim, so most production incidents will be provider incidents (quota exhaustion, 403 from a misconfigured key, TLS/proxy failures) rather than package bugs. Support ownership should sit with the team that owns the provider contract and billing account.
  • The chain fallback is a real support lever: a second provider means a primary outage degrades rather than fails. It is not configured by default in a meaningful way (GeoPlugin is not a substitute for a paid geocoder for address resolution), so if resilience matters, add an actual second geocoder to the chain.
  • No built-in circuit breaker. A provider returning errors will be retried per the adapter config and then bubble; without caching in front, a provider outage becomes a latency incident.

Scaling

  • The cache is the entire scaling story. With a dedicated Redis store and a sane TTL, hit rates are high because address→coordinate pairs are heavily repeated. Per-query doNotCache() should be reserved for cases where staleness is genuinely unacceptable, since each call is real money and real latency.
  • The hard ceiling is external quota, not application throughput. Size the provider tier against peak QPS × expected miss rate, not against total request volume.
  • Cache key must include locale (the package already caches separately per locale — good), and if you add region or provider-specific options, verify they participate in the key. Two callers using different locales/options must not collide.
  • Reverse geocoding at high precision produces near-unique keys and therefore near-zero hit rate. Round coordinates before caching if the business requirement tolerates it.

Failure modes

  • Empty result, not exception. ->get() returns an empty Collection for unresolvable input. Code that assumes [0] exists will throw; code that treats empty as an error will surface bad UX for legitimately vague addresses. Decide explicitly.
  • Quota/rate-limit exhaustion → HTTP error surfaced from the adapter; no graceful degradation by default.
  • API key or HTTPS misconfiguration with Google — the README calls out that an API key requires HTTPS. This fails as a provider error and is a recurring support ticket.
  • Cache deserialization corruption under Laravel 13 if serializable_classes is neither auto-registered nor explicitly allow-listed → __PHP_Incomplete_Class errors that look like cache-layer bugs.
  • Timeout-induced latency amplification in the request path if timeouts are left at defaults and no cache is warm.
  • Silent wrongness from locale/region config — results are valid but formatted or scoped unexpectedly, which is harder to detect than an error.
  • Adapter constructor argument mismatch — fails at first call, not at boot; caught only by exercising the code path in CI.

Ramp-up

  • Essentially negligible for a Laravel developer: the API is three verbs (geocode, reverse, geocodeQuery) plus locale(), using(), doNotCache(), dump(). A competent engineer is productive in under an hour using the README alone.
  • The non-obvious ramp-up is conceptual, not syntactic: understanding the chain-provider selection semantics, that caching is the primary cost/latency control, and that the provider(s) — not the package — determine correctness. Budget a short design review covering provider choice, cache TTL/ToS, and the empty-result contract; that review is where the actual risk lives.
  • Provide the team a single internal wrapper rather than raw app('geocoder') calls, so the empty-result contract, locale defaults, and caching policy are enforced in one place instead of being re-derived at every call site.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel