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

Geoip Laravel Package

maxmind/geoip

Laravel wrapper for MaxMind GeoIP databases that resolves IP addresses to geographic data such as country, region, city, and coordinates. Includes configuration, a service provider, and a simple API for GeoIP lookups, with support for local GeoIP2/MMDB files.

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle wraps MaxMind's legacy GeoIP C-API (the .dat binary databases), not GeoIP2 .mmdb. Before writing any code, confirm the package name in composer.json — the repository is IDCI-Consulting/Maxmind-GeoIp but the Packagist name and the Symfony bundle alias may differ (conventionally idci/maxmind-geoip-bundle with service alias idci_maxmind_geoip). Also check the require block: it targets PHP 5.3+/Symfony 2.x, so you'll want to know exactly which Symfony constraints it declares before dropping it into anything modern.

Minimal path:

  1. composer require idci/maxmind-geoip-bundle (verify the real name first).
  2. Register the bundle in app/AppKernel.php: new IDCI\Bundle\MaxmindGeoIpBundle\IDCIMaxmindGeoIpBundle().
  3. Obtain a legacy database file (GeoIP.dat for country, GeoLiteCity.dat for city) and point the bundle config at it, e.g. idci_maxmind_geoip: { database: "%kernel.root_dir%/../data/GeoLiteCity.dat", mode: memory }.
  4. Read DependencyInjection/Configuration.php and Resources/config/services.yml inside the bundle — that's the ground truth for the config keys, the service id, and which lookup methods (country code, record, org, city) are actually exposed. Don't trust README snippets from 2016.
  5. First use case: inject the service into a controller or a kernel.request listener and resolve the visitor's country code from $request->getClientIp() to drive a geo-redirect, a shipping/currency banner, or a default locale.

If you can't get a legacy .dat file at all, stop here — the bundle has no database and won't do anything useful; go straight to geoip2/geoip2.

Implementation Patterns

Wrap the vendor service, don't call it directly. The bundle returns raw arrays/false-y values in legacy MaxMind style. Put a thin GeoIpResolver of your own in front of it that returns a small DTO (countryCode, city, lat/lon, isResolved) and normalizes failure to null. That gives you one place to swap in GeoIP2 later without touching call sites.

Request-scoped lookup, decorator cache. Resolve the IP once per request (a listener that stashes the result on the request attributes), and memoize per-IP in a small array cache or PSR-6 pool for request-scoped and long-running (worker/queue) processes. Repeat lookups in the same request are common — e.g. locale detection, currency, tax, and Twig helpers all wanting the country.

kernel.request listener for geo-detection. Resolve early, store on the request, and let downstream services (locale negotiator, price resolver) read it. Keep the lookup non-fatal: an unresolvable IP must never 500 the page.

Twig extension. A geoip_country() function is the single most-requested thing from product/marketing. Back it with the request attribute so templates never trigger a DB lookup.

Bulk enrichment as a command. For ETL/analytics, write a console command that chunks rows, uses memory mode once per process (not per row), and writes results incrementally. This is where the package is actually fast; per-request lookups are dominated by mode choice, not the lookup itself.

Integration with Symfony's trusted proxies. If you're behind a load balancer, configure framework.trusted_proxies and read the IP through getClientIp() — never parse X-Forwarded-For yourself for a geo decision.

Testing seam. Because the underlying library is a static/binary-backed API, define an interface (GeoIpLookupInterface) in your app and bind the bundle's service as the implementation. Tests then use a fixture-backed fake and never need a .dat file or the extension.

Gotchas and Tips

  • The database supply chain is the real problem. MaxMind retired GeoLite Legacy (Jan 2019) and the legacy paid databases; there's no first-party download anymore. If your only source is a stale .dat, your accuracy decays every month. Treat this bundle as a stopgap and plan the migration to geoip2/geoip2 + .mmdb (the GeoIP2 PHP reader works on PHP 7+/8 and needs no extension).
  • Private and reserved IPs return nothing. 127.0.0.1, 10.x, 192.168.x, and often IPv6-on-IPv4-edition DBs give false/empty. Every call site must handle "unknown country" explicitly; don't let it silently become US.
  • Edition mismatch is silent. Asking a country-only GeoIP.dat for city/coordinates returns nothing rather than throwing. Match the lookup method to the file you shipped, and assert this in a smoke test.
  • Memory mode costs RAM per worker. memory loads the whole file into each PHP-FPM worker. A city DB is tens of MB — multiply by worker count before enabling it in production. shared/standalone modes trade CPU for memory.
  • PHP 8 / Symfony 4+ compatibility is unverified and unlikely. This is a 2016, PHP 5.3-targeted release with 27 stars and zero dependents. It will not be auto-configured under Flex, and older code patterns may break on PHP 8. If you must use it, pin the version, fork it, or bypass the bundle entirely and instantiate the underlying class through a service definition you control.
  • Missing/corrupt DB path fails at runtime, not compile time. Add a container boot check or a health-check command that asserts the file exists and a known IP resolves correctly — otherwise you discover the broken path in production.
  • Service id and config keys drift from the README. Read Configuration.php and services.yml. If the alias isn't what you expected, debug:container | grep -i geoip finds it fast.
  • No security or maintenance upstream. Zero dependents means nobody else is filing bugs. Budget for a fork if this becomes load-bearing; the extension point you want is your own GeoIpLookupInterface, not the bundle's internals.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle