samsmithcodes / laravel-geoip2
A Laravel package to enable IP lookups on the GeoIP2 Lite databases.
Package info
gitlab.samsmith.codes/samsmithcodes/laravel-geoip2
pkg:composer/samsmithcodes/laravel-geoip2
Requires
- php: ^8.2
- ext-phar: *
- ext-zlib: *
- geoip2/geoip2: ^3.0
- illuminate/console: ^12.0|^13.0
- illuminate/filesystem: ^12.0|^13.0
- illuminate/http: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
- illuminate/validation: ^12.0|^13.0
Requires (Dev)
- larastan/larastan: ^3.9
- laravel/pao: ^1.0
- laravel/pint: ^1.29
- orchestra/testbench: ^10.0||^11.0
- pestphp/pest: ^4.6||^5.0
- pestphp/pest-plugin-laravel: ^4.1||^5.0
- pestphp/pest-plugin-type-coverage: ^4.0||^5.0
- phpstan/extension-installer: ^1.4
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Laravel GeoIP2
A Laravel package to enable IP lookups on the GeoIP2 Lite databases.
Installation
You can install the package via Composer:
composer require samsmithcodes/laravel-geoip2
You may publish the configuration file:
php artisan vendor:publish --tag="geoip2-config"
Usage
Testing
First, download MaxMind's test databases, which aren't committed to the repository (see Test databases):
for db in GeoLite2-City-Test GeoLite2-ASN-Test; do
curl -fsSL --create-dirs -o "tests/Fixtures/$db.mmdb" \
"https://raw.githubusercontent.com/maxmind/MaxMind-DB/main/test-data/$db.mmdb"
done
You only need to do this once. Then run the full test suite with Docker, so you don't need PHP installed locally:
docker run --rm -it \
-v ${PWD}:/app \
registry.samsmith.codes/samsmithcodes/laravel-starter-tools:latest composer test
To run something else, swap composer test at the end of the command for:
- One of the steps below, e.g.
composer lintto fix the code style. - A single test file, e.g.
vendor/bin/pest tests/Feature/GeoIP2Test.php. - Only the tests with a name matching a filter, e.g.
vendor/bin/pest --filter="checksum".
What composer test runs
The steps are Composer scripts, defined under scripts in composer.json. They run in this order, and stop at the first failure:
| Step | Tool | What it checks | Config |
|---|---|---|---|
composer analyse | PHPStan with Larastan | The code is type safe and has no bugs it can find | phpstan.neon.dist |
composer lint:check | Laravel Pint | The code style is consistent | pint.json |
composer test:types | Pest type coverage | Every parameter, property and return in src has a type | composer.json |
composer test:unit | Pest with Orchestra Testbench | The tests in tests pass, run in parallel | phpunit.xml.dist, tests/Pest.php, tests/TestCase.php |
The tools
Pest runs the tests. It's built on PHPUnit, so it reads PHPUnit's config:
- phpunit.xml.dist lists the test suites (Arch, Feature and Unit) and the
srcdirectory being tested. It runs the tests in a random order, so they can't rely on each other, and fails on warnings or unexpected output. To add a test, create a file ending inTest.phpintests/Featureortests/Unitand it's picked up automatically. - tests/Pest.php runs before the tests, and makes every test use
TestCase. Add any helpers shared between test files here. - tests/ArchTest.php uses Pest's architecture testing to enforce rules across the code, e.g. strict types, and no
dd()or insecure functions likemd5().
Orchestra Testbench boots a minimal Laravel app for the tests, so the package is tested just as an app would use it:
- tests/TestCase.php loads the package's service provider in
getPackageProviders(), and sets the config every test starts with indefineEnvironment(), which points the databases at the test fixtures. A test can change config for itself withconfig([...]). - testbench.yaml and the
workbenchdirectory configure the app used bycomposer serve, for trying the package in a browser. The tests don't use them.
Pest type coverage checks everything in src has a type declared. It's configured by the options on the test:types script in composer.json: --min=100 is the percentage required, and --memory-limit raises PHP's memory limit, which the Docker image's default is too low for.
PHPStan, with the Larastan extension so it understands Laravel's facades and helpers, reads the code without running it to find bugs, e.g. passing the wrong type or calling a method that doesn't exist. phpstan.neon.dist sets:
level, how strict it is, from 0 to 10, currently 7.paths, the directories it checks.ignoreErrors, for false positives, each with a comment saying why. Only add one when the error is wrong, not to hide a real problem.
Laravel Pint checks the code style. pint.json uses Laravel's preset, with a few extra rules, e.g. a blank line before every return. composer lint:check only reports problems, while composer lint fixes them.
The tests
tests/ArchTest.php: architecture rules, e.g. every file declares strict types, and there are no debugging calls likedd()or insecure functions.tests/Feature/GeoIP2Test.php: looks up real addresses in the test databases (City, ASN and IPv6), and checks the errors for invalid addresses, missing databases, and databases that are the wrong type. It also checks a database is reopened when its file changes, as happens after an update.tests/Feature/UpdateCommandTest.php: runsgeoip2:updateagainst a fake MaxMind built withHttp::fake(), which serves real archives containing the test databases. It covers downloading, skipping up to date databases,--force, missing or rejected credentials, and a bad checksum leaving the current database untouched. No real requests are made.tests/Feature/ServiceProviderTest.php: the container bindings, config, Facade and command are registered.tests/Unit/RecordTest.php: MaxMind's City and ASN models are mapped onto aRecordcorrectly, including when one is missing.
Test databases
The tests use two of MaxMind's official test databases, which contain fake data for a handful of addresses:
GeoLite2-City-Test.mmdbGeoLite2-ASN-Test.mmdb
They come from the maxmind/MaxMind-DB repository, and are downloaded into tests/Fixtures, where the tests load them with Pest's fixture() helper. They're ignored by Git, in .gitignore, so they aren't redistributed with this package. If they're missing, every test fails with "The fixture file [...] does not exist", so download them with the command at the top of this section.
The download always uses MaxMind's latest test data, from the main branch, so the tests keep up with any changes MaxMind makes. The tests check exact values from these databases, e.g. that 2.125.160.216 is in Boxford, so if MaxMind changes their test data some tests may start failing. When that happens, download the databases again and update the expected values in tests/Feature/GeoIP2Test.php. The source JSON shows which addresses each database contains.
The real GeoLite2 databases are never used in the tests.
License
Laravel GeoIP2 is open-sourced software licensed under the MIT license.