Weave Code
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 Package

willdurand/geocoder

Powerful PHP geocoding library by William Durand. Geocode addresses to coordinates and reverse-geocode lat/long back to locations, with a clean provider-based API. Supports multiple geocoding services, adapters, caching, and easy integration in any project.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation

    composer require willdurand/geocoder
    

    Add the provider to config/app.php:

    'providers' => [
        // ...
        Geocoder\Provider\GeocoderServiceProvider::class,
    ],
    
  2. Basic Setup Configure providers in config/geocoder.php (auto-generated after installation):

    'providers' => [
        'google_maps' => [
            'key' => env('GOOGLE_MAPS_API_KEY'),
        ],
        'openstreetmap' => [
            'host' => 'https://nominatim.openstreetmap.org',
        ],
    ],
    
  3. First Use Case: Reverse Geocoding

    use Geocoder\Geocoder;
    use Geocoder\Provider\GoogleMapsProvider;
    
    $geocoder = new Geocoder();
    $geocoder->registerProvider(new GoogleMapsProvider());
    
    $results = $geocoder->reverse(48.8566, 2.3522); // Latitude, Longitude
    foreach ($results as $result) {
        dd($result->getCoordinates(), $result->getFormattedAddress());
    }
    

Implementation Patterns

Common Workflows

  1. Forward Geocoding (Address → Coordinates)

    $results = $geocoder->geocodeQuery('1600 Amphitheatre Parkway, Mountain View, CA');
    $coordinates = $results->first()->getCoordinates();
    
  2. Batch Processing

    $addresses = ['Paris', 'Berlin', 'Tokyo'];
    $geocoder->batch($addresses, function ($result, $address) {
        // Handle each result
    });
    
  3. Fallback Providers

    $geocoder->registerProvider(new OpenStreetMapProvider());
    $geocoder->registerProvider(new GoogleMapsProvider());
    
    $results = $geocoder->geocodeQuery('Unknown Place');
    // Falls back to OpenStreetMap if Google fails.
    
  4. Caching Results

    $geocoder->registerProvider(new GoogleMapsProvider());
    $geocoder->registerCache(new \Geocoder\Cache\DoctrineCache());
    
    $results = $geocoder->geocodeQuery('Cached Address');
    
  5. Laravel Integration (Service Provider)

    // app/Providers/GeocoderServiceProvider.php
    use Geocoder\Geocoder;
    use Geocoder\Provider\GoogleMapsProvider;
    
    class GeocoderServiceProvider extends ServiceProvider {
        public function register() {
            $this->app->singleton(Geocoder::class, function () {
                $geocoder = new Geocoder();
                $geocoder->registerProvider(new GoogleMapsProvider());
                return $geocoder;
            });
        }
    }
    

    Then inject Geocoder into controllers/services:

    public function __construct(private Geocoder $geocoder) {}
    

Gotchas and Tips

Pitfalls

  1. API Key Management

    • Never hardcode API keys. Use Laravel’s .env:
      GOOGLE_MAPS_API_KEY=your_key_here
      
    • Some providers (e.g., OpenStreetMap) have usage limits or require email registration.
  2. Rate Limiting

    • Free tiers (e.g., Google Maps) have strict daily limits. Monitor usage via provider dashboards.
    • Implement retries with exponential backoff for failed requests:
      $geocoder->registerProvider(new GoogleMapsProvider(['retries' => 3]));
      
  3. Caching Quirks

    • Cache invalidation: Manually clear cache if addresses change (e.g., new businesses).
    • Avoid caching for real-time data (e.g., user-submitted locations).
  4. Provider-Specific Issues

    • Google Maps: Requires billing setup (even for free tier). Some endpoints may return OVER_QUERY_LIMIT.
    • OpenStreetMap: Nominatim has usage policies. Avoid scraping; use ?format=json&email=your@email.com.
  5. Precision Handling

    • Coordinates may vary slightly between providers. Normalize results (e.g., round to 6 decimal places):
      $lat = round($result->getLatitude(), 6);
      $lng = round($result->getLongitude(), 6);
      

Debugging Tips

  1. Enable Debug Mode

    $geocoder->registerProvider(new GoogleMapsProvider(['debug' => true]));
    

    Logs HTTP requests/responses to storage/logs/geocoder.log.

  2. Handle Exceptions

    try {
        $results = $geocoder->geocodeQuery('Invalid Address');
    } catch (\Geocoder\Exception\UnsupportedProvider $e) {
        // Fallback logic
    } catch (\Geocoder\Exception\NoResult $e) {
        // No match found
    }
    
  3. Test Locally

    • Use mockery to stub providers in tests:
      $mockProvider = \Mockery::mock(GoogleMapsProvider::class);
      $mockProvider->shouldReceive('geocode')->andReturn([$mockResult]);
      $geocoder->registerProvider($mockProvider);
      

Extension Points

  1. Custom Providers Extend Geocoder\Provider\AbstractProvider to integrate with proprietary APIs:

    class CustomProvider extends AbstractProvider {
        public function geocode($query) {
            $response = Http::get('https://api.custom.com/geocode', ['q' => $query]);
            return $this->createResultCollection($response->json());
        }
    }
    
  2. Result Transformers Modify results before use:

    $geocoder->registerProvider(new GoogleMapsProvider());
    $results = $geocoder->geocodeQuery('Paris');
    $transformed = $results->map(function ($result) {
        return [
            'address' => $result->getFormattedAddress(),
            'confidence' => $result->getConfidence(),
        ];
    });
    
  3. Laravel Eloquent Integration Add geocoding to models:

    // app/Models/Location.php
    use Geocoder\Geocoder;
    
    class Location extends Model {
        public function resolveRouteBinding($value, $field = null) {
            $geocoder = app(Geocoder::class);
            $results = $geocoder->geocodeQuery($value);
            return $results->first()?->getCoordinates();
        }
    }
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor