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

Location Laravel Package

stevebauman/location

Retrieve a user’s geolocation from their IP in Laravel. Provides a simple Location facade to get city, region, country, coordinates, timezone and more, with multiple driver support (e.g., IP2Location, IP-API, MaxMind) plus caching and testing helpers.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require stevebauman/location
    
  2. Publish config (optional, but recommended for customization):
    php artisan vendor:publish --provider="Stevebauman\Location\LocationServiceProvider"
    
  3. Configure your driver in .env (example for MaxMind):
    LOCATION_DRIVER=maxmind
    MAXMIND_LICENSE_KEY=your_license_key_here
    
  4. First use case: Retrieve a user’s location in a controller or middleware:
    use Stevebauman\Location\Facades\Location;
    
    $position = Location::get();
    $country = $position->country;
    $city = $position->city;
    

Where to Look First

  • Configuration: config/location.php – Driver settings, timeouts, and fallback logic.
  • Facade: Stevebauman\Location\Facades\Location – Primary entry point for all operations.
  • Position Model: Stevebauman\Location\Position – Represents location data (e.g., country, latitude, timezone).
  • Testing: Location::fake() – Simulate locations for tests or development.

Implementation Patterns

Core Workflows

1. Middleware for Global Geo-Data

Attach location data to every request via middleware:

// app/Http/Middleware/AttachGeoData.php
public function handle($request, Closure $next) {
    $request->merge([
        'geo' => Location::get()->toArray(),
    ]);
    return $next($request);
}

Register in app/Http/Kernel.php:

protected $middleware = [
    // ...
    \App\Http\Middleware\AttachGeoData::class,
];

2. Dynamic Content Based on Location

Use the facade in Blade templates or controllers:

// app/Http/Controllers/PageController.php
public function show() {
    $position = Location::get();
    return view('welcome', [
        'currency' => $position->currencyCode,
        'language' => $position->countryCode === 'US' ? 'en' : 'es',
    ]);
}

3. Fallback Drivers

Configure fallbacks in config/location.php:

'drivers' => [
    'maxmind' => [
        'enabled' => true,
        'fallback' => 'ipinfo',
    ],
    'ipinfo' => [
        'enabled' => true,
        'fallback' => false,
    ],
],

4. Caching for Performance

Leverage Laravel’s cache to reduce API calls:

$position = Location::get(); // Uses cache by default (TTL: 1 hour)
$position = Location::get(['cache' => false]); // Bypass cache

5. Testing with Fake Locations

Simulate locations in tests:

Location::fake([
    'country' => 'DE',
    'city' => 'Berlin',
    'latitude' => 52.5200,
]);

$position = Location::get(); // Returns fake data

Integration Tips

Middleware for Geo-Blocking

Block access based on location:

// app/Http/Middleware/GeoBlock.php
public function handle($request, Closure $next) {
    $position = Location::get();
    if ($position->countryCode === 'RU') {
        abort(403, 'Access denied from your region.');
    }
    return $next($request);
}

Extend Position with Custom Fields

Add methods to the Position model via macros:

// app/Providers/AppServiceProvider.php
use Stevebauman\Location\Position;

public function boot() {
    Position::macro('isEu', function () {
        $euCountries = ['AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', /* ... */];
        return in_array($this->countryCode, $euCountries);
    });
}

// Usage:
$position = Location::get();
if ($position->isEu()) {
    // Apply EU-specific logic
}

Custom Drivers

Create a driver for a proprietary API:

// app/Providers/LocationServiceProvider.php
use Stevebauman\Location\Contracts\Driver;

class CustomDriver implements Driver {
    public function get($ip = null) {
        $response = Http::get('https://api.your-service.com/geo', [
            'ip' => $ip ?? request()->ip(),
        ]);
        return new Position($response->json());
    }
}

// Register in config/location.php:
'drivers' => [
    'custom' => [
        'class' => \App\Providers\CustomDriver::class,
    ],
],

Bulk Lookups

For batch processing (e.g., analytics), fetch multiple IPs:

$ips = ['192.168.1.1', '8.8.8.8'];
$positions = Location::get($ips); // Returns collection of Position objects

Gotchas and Tips

Pitfalls

  1. MaxMind Database Updates

    • Issue: Auto-updates may fail on shared hosting due to permissions or storage limits.
    • Fix: Set MAXMIND_AUTO_UPDATE=false in .env and manually update:
      php artisan location:update
      
    • Storage: Ensure the storage/app/maxmind directory is writable and has enough space (~5MB per database).
  2. IPv6 Support

    • Issue: Some drivers (e.g., older ipapi.co) may not support IPv6.
    • Fix: Test with IPv6 addresses and switch to a driver like ipinfo or maxmind if needed.
  3. Fallback Logic Failures

    • Issue: Circular fallbacks (e.g., driver1 falls back to driver2, which falls back to driver1) cause infinite loops.
    • Fix: Set fallback: false for the last driver in the chain:
      'drivers' => [
          'maxmind' => ['fallback' => 'ipinfo'],
          'ipinfo' => ['fallback' => false],
      ],
      
  4. Timezone Inconsistencies

    • Issue: Some drivers (e.g., early versions of MaxMind) return incorrect timezones.
    • Fix: Use the timezone field from the Position object and validate it:
      $position = Location::get();
      if (!in_array($position->timezone, DateTimeZone::listIdentifiers())) {
          $position->timezone = 'UTC'; // Fallback
      }
      
  5. Rate Limiting on API Drivers

    • Issue: Free-tier APIs (e.g., ipinfo.io) throttle requests.
    • Fix: Cache aggressively and monitor usage:
      Location::get(['cache' => true, 'cache_ttl' => 3600]); // Cache for 1 hour
      
  6. Windows Path Issues

    • Issue: MaxMind database extraction fails on Windows due to path separators.
    • Fix: Ensure storage/app/maxmind is configured correctly in config/location.php:
      'maxmind' => [
          'path' => storage_path('app/maxmind'),
      ],
      

Debugging Tips

  1. Check Driver Responses Enable debug mode to log raw responses:

    Location::setDebug(true);
    $position = Location::get(); // Logs driver responses to Laravel logs
    
  2. Validate IP Addresses Ensure the IP passed to the driver is valid:

    use Stevebauman\Location\Support\IpAddress;
    
    $ip = IpAddress::make('2001:0db8:85a3::8a2e:0370:7334');
    $position = Location::get($ip);
    
  3. Test Fallbacks Manually Disable primary drivers to test fallbacks:

    Location::extend('maxmind', function () {
        throw new \RuntimeException('Simulate maxmind failure');
    });
    $position = Location::get(); // Should use fallback
    
  4. Handle Missing Data Some drivers may return null for optional fields (e.g., postalCode). Normalize data:

    $postal = $position->postalCode ?? 'N/A';
    

Configuration Quirks

  1. MaxMind License Key

    • Location: MAXMIND_LICENSE_KEY in .env or config/location.php.
    • Note: The key is not the same as your MaxMind account username. Generate it in the MaxMind account portal.
  2. Driver-Specific Settings

    • ipinfo.io: Requires an API token (IPIINFO_TOKEN in .env).
    • IP2Location: Needs a database file (IP2LOCATION_DATABASE_PATH).
    • Cloudflare: May require additional
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.
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
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope