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

Nominatim Provider Laravel Package

geocoder-php/nominatim-provider

Nominatim provider for Geocoder PHP. Adds OpenStreetMap Nominatim geocoding and reverse geocoding support, converting addresses and coordinates to structured results, with configurable endpoints and HTTP client integration for Laravel/PHP apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require geocoder-php/geocoder geocoder-php/nominatim-provider
    
    • Ensure geocoder-php/geocoder is installed as the base package.
  2. Basic Usage

    use Geocoder\Geocoder;
    use Geocoder\Provider\Nominatim\NominatimProvider;
    
    $geocoder = new Geocoder([
        'nominatim' => [
            'key' => 'YOUR_NOMINATIM_API_KEY', // Optional, but recommended
            'host' => 'https://nominatim.openstreetmap.org', // Default host
        ],
    ]);
    
    // Geocode an address
    $results = $geocoder->geocode('1600 Amphitheatre Parkway, Mountain View, CA');
    foreach ($results as $result) {
        echo $result->getPosition()->getLatitude() . ', ' . $result->getPosition()->getLongitude();
    }
    
    // Reverse geocode coordinates
    $results = $geocoder->reverseGeocode('37.4220, -122.0841');
    foreach ($results as $result) {
        echo $result->getStreet() . ', ' . $result->getLocality();
    }
    
  3. First Use Case

    • Form Validation: Use Nominatim to validate and geocode user-submitted addresses in real-time during form submission.
    • Example:
      use Illuminate\Support\Facades\Validator;
      
      $validator = Validator::make($request->all(), [
          'address' => 'required|geocode', // Custom rule to validate geocoding
      ]);
      

Implementation Patterns

Common Workflows

  1. Batch Geocoding Useful for processing large datasets (e.g., CSV imports):

    $addresses = ['Address 1', 'Address 2', 'Address 3'];
    $geocoded = [];
    
    foreach ($addresses as $address) {
        $results = $geocoder->geocode($address);
        $geocoded[] = $results->first()?->getPosition();
    }
    
  2. Caching Results Avoid hitting Nominatim’s rate limits by caching responses:

    use Illuminate\Support\Facades\Cache;
    
    $cachedKey = 'geocode_' . md5($address);
    $results = Cache::remember($cachedKey, now()->addHours(1), function () use ($geocoder, $address) {
        return $geocoder->geocode($address);
    });
    
  3. Fallback Providers Combine Nominatim with other providers (e.g., Google Maps) for redundancy:

    $geocoder = new Geocoder([
        'nominatim' => [...],
        'google_maps' => [...], // Requires geocoder-php/google-maps-provider
    ]);
    $results = $geocoder->geocodeQuery('1600 Amphitheatre Parkway')->first();
    
  4. Laravel Service Provider Integration Bind the geocoder to Laravel’s container for easy dependency injection:

    // app/Providers/AppServiceProvider.php
    public function register()
    {
        $this->app->singleton(Geocoder::class, function () {
            return new Geocoder([
                'nominatim' => [
                    'key' => config('services.nominatim.key'),
                ],
            ]);
        });
    }
    
  5. Customizing Request Options Nominatim supports query parameters like format, addressdetails, or viewbox:

    $results = $geocoder->geocodeQuery('Paris')
        ->withOptions(['addressdetails' => 1, 'viewbox' => '1,1,2,2'])
        ->get();
    

Integration Tips

  1. Laravel Form Requests Extend FormRequest to validate geocoding:

    use Geocoder\Geocoder;
    
    public function rules()
    {
        return [
            'address' => 'required|string',
        ];
    }
    
    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            $geocoder = app(Geocoder::class);
            $results = $geocoder->geocode($this->address);
            if ($results->isEmpty()) {
                $validator->errors()->add('address', 'Invalid address.');
            }
        });
    }
    
  2. Eloquent Model Observers Automatically geocode addresses when a model is saved:

    // app/Observers/AddressObserver.php
    public function saved(Address $address)
    {
        if (empty($address->latitude)) {
            $results = $geocoder->geocode($address->full_address);
            $position = $results->first()?->getPosition();
            $address->update([
                'latitude' => $position?->getLatitude(),
                'longitude' => $position?->getLongitude(),
            ]);
        }
    }
    
  3. API Rate Limiting Nominatim has usage policies (see here). Implement middleware to throttle requests:

    // app/Http/Middleware/GeocodeThrottle.php
    public function handle($request, Closure $next)
    {
        $key = $request->ip() . '_geocode';
        $remaining = Cache::get($key, 1000); // Default: 1000 requests/day
    
        if ($remaining <= 0) {
            abort(429, 'Nominatim rate limit exceeded.');
        }
    
        Cache::decrement($key);
        return $next($request);
    }
    

Gotchas and Tips

Pitfalls

  1. Rate Limiting

    • Nominatim enforces strict usage policies. Exceeding limits (e.g., >1 request/second) may temporarily block your IP.
    • Fix: Use caching, batch processing, or a self-hosted Nominatim instance.
  2. Read-Only Access

    • The package is read-only. Nominatim does not support reverse operations (e.g., updating OSM data).
    • Workaround: Use a dedicated service like Photon for static map tiles if needed.
  3. Deprecated Hosts

    • Avoid using nominatim.openstreetmap.org for production without an API key. Use a dedicated instance (e.g., nominatim.example.com) or pay for a commercial license.
    • Tip: Check Nominatim’s status page for outages.
  4. Inconsistent Results

    • Nominatim may return partial or ambiguous results for poorly formatted addresses (e.g., "New York" vs. "New York, NY").
    • Fix: Append a city/state/country to queries (e.g., "New York, NY, USA").
  5. Timeouts

    • Slow responses may occur during peak times. Nominatim recommends:
      • Using https://nominatim.openstreetmap.org/search for simple queries.
      • Using https://nominatim.openstreetmap.org/reverse for reverse geocoding.
    • Fix: Implement retry logic with exponential backoff.

Debugging

  1. Enable Debugging Enable Guzzle’s debug mode to inspect raw responses:

    $geocoder = new Geocoder([
        'nominatim' => [
            'key' => 'YOUR_KEY',
            'http_client' => new \GuzzleHttp\Client([
                'debug' => true,
            ]),
        ],
    ]);
    
  2. Validate API Responses Nominatim returns JSON with a status field. Check for errors:

    $results = $geocoder->geocode('invalid address');
    if ($results->isEmpty()) {
        $lastResponse = $geocoder->getProvider('nominatim')->getLastResponse();
        Log::error('Nominatim error:', ['response' => $lastResponse]);
    }
    
  3. Common HTTP Errors

    • 400 Bad Request: Invalid query or parameters.
    • 403 Forbidden: Missing API key or rate-limited.
    • 503 Service Unavailable: Nominatim is down (check status page).

Extension Points

  1. Custom Nominatim Instance Configure a private Nominatim instance (e.g., self-hosted):

    $geocoder = new Geocoder([
        'nominatim' => [
            'host' => 'https://your-nominatim-instance.com',
            'scheme' => 'https',
            'port' => 443,
        ],
    ]);
    
  2. Add Custom Fields Nominatim supports addressdetails for structured data. Parse it in Laravel:

    $result = $ge
    
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.
terminal42/code-quality-tools
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