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

Geoip2 Provider Laravel Package

geocoder-php/geoip2-provider

GeoIP2 provider for PHP Geocoder using MaxMind GeoLite2/GeoIP2 databases or the paid Precision web service. Geocode IP addresses via a GeoIP2 adapter to return location data (city/country) from MMDB files or API.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require geocoder-php/geoip2-provider
    
  2. Download a MaxMind GeoIP2 database (e.g., GeoLite2).
  3. Basic usage in Laravel:
    use Geocoder\Geocoder;
    use Geocoder\Provider\GeoIP2\GeoIP2;
    use Geocoder\Provider\GeoIP2\GeoIP2Adapter;
    use GeoIp2\Database\Reader;
    
    $reader = new Reader(storage_path('app/GeoLite2-City.mmdb'));
    $adapter = new GeoIP2Adapter($reader);
    $geocoder = new GeoIP2($adapter);
    
    $ip = '74.200.247.59';
    $address = $geocoder->geocodeQuery(\Geocoder\Query\GeocodeQuery::create($ip))->first();
    

First Use Case

  • Logging user locations: Attach geolocation data to user sessions or requests.
    $ip = request()->ip();
    $location = $geocoder->geocodeQuery(\Geocoder\Query\GeocodeQuery::create($ip))->first();
    $user->update(['country' => $location->getCountry()]);
    

Implementation Patterns

Common Workflows

  1. Caching Results (Critical for performance):

    $cache = new \Geocoder\Cache\DoctrineCache(new \Doctrine\Common\Cache\FilesystemCache(storage_path('app/cache')));
    $geocoder = new GeoIP2($adapter, $cache);
    
    • Use Laravel’s built-in cache (Cache::remember()) for simplicity.
  2. Batch Processing:

    $ips = ['1.1.1.1', '2.2.2.2', '3.3.3.3'];
    $results = collect($ips)->map(fn($ip) => $geocoder->geocodeQuery(\Geocoder\Query\GeocodeQuery::create($ip))->first());
    
  3. Integration with Laravel Middleware:

    public function handle($request, Closure $next) {
        $ip = $request->ip();
        $location = $geocoder->geocodeQuery(\Geocoder\Query\GeocodeQuery::create($ip))->first();
        $request->merge(['geo_data' => $location]);
        return $next($request);
    }
    

Laravel-Specific Tips

  • Service Provider Binding:
    public function register() {
        $this->app->singleton(Geocoder::class, function ($app) {
            $reader = new Reader(storage_path('app/GeoLite2-City.mmdb'));
            $adapter = new GeoIP2Adapter($reader);
            return new GeoIP2($adapter, $app['cache']);
        });
    }
    
  • Configurable Database Path:
    // config/geocoder.php
    'geoip2' => [
        'database_path' => storage_path('app/GeoLite2-City.mmdb'),
    ];
    
    $reader = new Reader(config('geocoder.geoip2.database_path'));
    

Gotchas and Tips

Pitfalls

  1. Database File Permissions:

    • Ensure the Laravel storage directory (storage/app/) is writable by the web server.
    • Fix: Run chmod -R 755 storage/ or use storage_path('app') with absolute paths.
  2. IPv6 Support:

    • GeoIP2 databases may not fully support IPv6. Test with inet_pton() to validate IPs:
      if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
          // Handle IPv6-specific logic
      }
      
  3. Rate Limiting (Web Service):

    • The MaxMind API has strict rate limits. Cache aggressively or use a queue system for bulk lookups.
  4. Time Zone Data:

    • GeoIP2 databases include time zone data, but it’s not always accurate. Validate with DateTimeZone:
      $timeZone = $location->getTimeZone();
      if (!$timeZone) {
          $timeZone = 'UTC'; // Fallback
      }
      

Debugging

  • Check Database Validity:
    try {
        $reader->city($ip); // Throws \GeoIp2\Exception\AddressNotFoundException if invalid
    } catch (\Exception $e) {
        Log::error("GeoIP2 DB error: " . $e->getMessage());
    }
    
  • Log Missing Data:
    if (!$location->getCountry()) {
        Log::warning("No country data for IP: {$ip}");
    }
    

Extension Points

  1. Custom Response Mapping:

    • Extend GeoIP2Adapter to transform raw GeoIP2 responses:
      class CustomGeoIP2Adapter extends GeoIP2Adapter {
          public function get($query) {
              $result = parent::get($query);
              return $result->withCoordinates(
                  $result->getLatitude() + 0.1, // Offset for testing
                  $result->getLongitude()
              );
          }
      }
      
  2. Fallback Providers:

    • Combine with other providers (e.g., geocoder-php/google-maps-provider) for redundancy:
      $geocoder = new \Geocoder\Geocoder();
      $geocoder->registerProvider(new GeoIP2($adapter));
      $geocoder->registerProvider(new \Geocoder\Provider\GoogleMaps\GoogleMaps());
      
  3. Environment-Specific Config:

    • Use Laravel’s config('app.env') to switch between local (database) and production (API) setups:
      $reader = config('app.env') === 'production'
          ? new \GeoIp2\WebService\Client(env('MAXMIND_ACCOUNT_ID'), env('MAXMIND_LICENSE_KEY'))
          : new Reader(storage_path('app/GeoLite2-City.mmdb'));
      

Performance

  • Preload Database:
    • Initialize the Reader early (e.g., in a service provider’s boot()) to avoid lazy-loading delays.
  • Avoid Redundant Lookups:
    • Store IP-to-location mappings in a database table (e.g., ip_geolocations) for frequently accessed IPs.
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle