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

Geo Ip Laravel Package

arcanedev/geo-ip

Laravel package for IP geolocation with a simple, unified API. Supports multiple providers such as MaxMind and IP2Location, letting you look up country, city, coordinates, and other location data from an IP address.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and pull in its MaxMind dependency:

composer require arcanedev/geo-ip

On Laravel 5.5+ the Arcanedev\GeoIP\GeoIPServiceProvider and the GeoIP facade are auto-discovered. On older apps add them manually to config/app.php:

'providers' => [
    Arcanedev\GeoIP\GeoIPServiceProvider::class,
],
'aliases' => [
    'GeoIP' => Arcanedev\GeoIP\Facades\GeoIP::class,
],

Publish the config and set up the database:

php artisan vendor:publish --provider="Arcanedev\GeoIP\GeoIPServiceProvider" --tag=config
php artisan geoip:update   # downloads the MaxMind DB using your license key

Then set in .env:

MAXMIND_LICENSE_KEY=your-key
MAXMIND_USER_ID=your-account-id

First real use case — resolve the visitor's location in a controller or middleware:

$location = GeoIP::getLocation(request()->ip());

$location->isoCode;   // "US"
$location->country;   // "United States"
$location->city;      // "Mountain View"
$location->timezone;  // "America/Los_Angeles"
$location->default;   // true if the lookup failed

Where to look first:

  • config/geoip.php — drivers (maxmind, ipapi), database_path, license_key, user_id, and the default_location fallback array.
  • Arcanedev\GeoIP\GeoIP — the singleton behind the facade, exposes getLocation() and driver accessors.
  • Arcanedev\GeoIP\Entities\Location — the value object returned by lookups (toArray() / toJson() for serialization).

Implementation Patterns

Middleware that tags every request. Resolve once and stash the result so downstream code doesn't re-read the mmdb file:

public function handle($request, Closure $next)
{
    $request->attributes->set('geo', GeoIP::getLocation($request->ip()));

    return $next($request);
}

Locale / timezone selection. The most common day-to-day win — pick a language or display timezone from the country code, with a safe default:

$locale = in_array($location->isoCode, ['FR', 'BE', 'CA']) ? 'fr' : 'en';
app()->setLocale($locale);

Currency, tax, and shipping logic. Country-level lookups are cheap and stable; use isoCode for VAT rules, price display, and shipping eligibility. Keep country logic in a config map rather than scattering if statements across controllers.

Geo-restrictions / compliance. Gate content or features by country in a policy or middleware:

abort_unless(in_array($geo->isoCode, config('geo.allowed_countries')), 403);

Caching lookups. Both drivers benefit — MaxMind hits the filesystem, the ipapi driver makes a synchronous HTTP call:

$location = Cache::remember("geoip:{$ip}", now()->addDay(), fn () => GeoIP::getLocation($ip));

Storing on the user/order record. Persist isoCode, country, and city at signup or checkout rather than re-resolving later — IPs change and the DB is refreshed weekly.

Fallback handling. config('geoip.default_location') supplies the payload used for private/invalid IPs and failed lookups. Always branch on $location->default (or a null isoCode) before treating a value as authoritative:

if ($location->default) {
    // local dev, health checks, internal traffic
}

Testing. The facade resolves a container singleton named geoip; swap it in tests so nothing touches the mmdb file or network:

$this->app->instance('geoip', Mockery::mock(GeoIP::class, function ($m) {
    $m->shouldReceive('getLocation')->andReturn(new Location([...]));
}));

Alternatively set default_location in the test config and let every lookup fall back to it.

Serialization for APIs. $location->toArray() is convenient for JSON responses and logging; toJson() avoids a second encode step if you're returning it verbatim.

Gotchas and Tips

  • Maintenance status is the big one. Last release was Feb 2018 and it targets Laravel 5. The pinned geoip2/geoip2 and arcanedev/support versions can collide with modern Symfony/Laravel constraints. On Laravel 9+ it's often simpler to use geoip2/geoip2 directly — this package is a thin facade over it, so you lose very little.
  • The DB goes stale silently. MaxMind refreshes GeoLite2 weekly. Schedule php artisan geoip:update (or a cron that re-downloads the mmdb) — nothing errors when data is old, results just drift.
  • Never commit the mmdb. It's tens of megabytes, in storage/app/geoip/, and changes on every update. Add the directory to .gitignore and provision it in your deploy pipeline, or run geoip:update as a release step.
  • Private and reserved IPs always fall through. 127.0.0.1, 10.x, 192.168.x and friends return the default location. Local development will always look like default: true unless you stub it.
  • Attribute typos fail quietly. Location uses magic property access; $location->countryCode (wrong) returns null rather than throwing. Confirm field names with $location->toArray() — it's isoCode, not countryCode.
  • The ipapi driver is not production-grade. It's a synchronous call to a free public endpoint with rate limits and (historically) no HTTPS on the free tier. Use it for prototypes only; use maxmind with a local DB in production.
  • Long-running workers hold the file open. The reader is a singleton, so queue workers and Octane keep the old mmdb handle after geoip:update. Restart workers as part of the update step.
  • config:cache freezes the path. If database_path is env-driven, remember to rebuild the config cache on deploy or lookups will point at the old file.
  • Errors can throw. Lookup failures raise package exceptions; wrap in try/catch (or rescue()) when a location is nice-to-have and shouldn't 500 the request.
  • Smaller DB when you only need countries. Swap GeoLite2-City.mmdb for GeoLite2-Country.mmdb if all your logic keys off isoCode — much smaller file, faster reads.
  • Extension points: override default_location and driver config, bind your own implementation of the GeoIP contract to add caching or a corporate proxy/VPN header strategy, or add a custom driver alongside maxmind/ipapi if you need a paid vendor.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin