Retrieve a visitor's location from their IP address using various services (online & local).
Install location using composer require
:
composer require stevebauman/location
Publish the configuration file (this will create a location.php
file inside the config
directory):
php artisan vendor:publish --provider="StevebaumanLocationLocationServiceProvider"
use StevebaumanLocationFacadesLocation;
if ($position = Location::get()) {
// Successfully retrieved position.
echo $position->countryName;
} else {
// Failed retrieving position.
}
Important:
- This method retrieves the user's IP address via
request()->ip()
.- In the default configuration,
testing.enabled
is active, the returned IP address is in the USA. Disable it to get the client's real IP address.
$position = Location::get('192.168.1.1');
You may call Location::fake
with an array of IP address patterns and their expected positions to fake the location of an IP address:
use StevebaumanLocationPosition;
use StevebaumanLocationFacadesLocation;
Location::fake([
'127.0.0.1' => Position::make([
'countryName' => 'United States',
'countryCode' => 'US',
// ...
])
]);
// Somewhere in your application...
$position = Location::get('127.0.0.1'); // Position
If you prefer, you may use an asterisk to return the same position for any IP address that is given:
Location::fake([
'*' => Position::make([
'countryName' => 'United States',
'countryCode' => 'US',
// ...
])
]);
$position = Location::get($anyIpAddress); // Position
If no expectations are given, or an expectation is not matched, Location::get
will return false
:
Location::fake();
Location::get($anyIpAddress); // false
If your application attempts to retrieve the location's of multiple IP addresses, you may provide multiple IP address expectation patterns:
Location::fake([
'127.0.0.1' => Position::make([
'countryName' => 'United States',
'countryCode' => 'US',
// ...
]),
'192.168.1.1' => Position::make([
'countryName' => 'Canada',
'countryCode' => 'CA',
// ...
]),
]);
Available drivers:
It is encouraged to set up MaxMind as a fallback driver using a local database so that some location information is returned in the event of hitting a rate limit from the external web services.
To set up MaxMind to retrieve the user's location from your own server, you must:
.env
file using the MAXMIND_LICENSE_KEY
keyphp artisan location:update
to download the latest .mmdb
file into your database/maxmind
directoryNote: Keep in mind, you'll need to update this file by running
location:update
on a regular basis to retrieve the most current information from your visitors.
In the config file, you can specify as many fallback drivers as you wish. It is
recommended to configure the MaxMind driver with the local database .mmdb
file (mentioned above), so you are alwaysretrieving some generic location
information from the visitor.
If an exception occurs trying to grab a driver (such as a 400/500 error if the providers API changes), it will automatically use the next driver in line.
To create your own driver, simply create a class in your application, and extend the abstract Driver:
namespace AppLocationDrivers;
use IlluminateSupportFluent;
use IlluminateSupportFacadesHttp;
use StevebaumanLocationPosition;
use StevebaumanLocationRequest;
use StevebaumanLocationDriversDriver;
class MyDriver extends Driver
{
protected function process(Request $request): Fluent
{
$response = Http::get("https://driver-url.com", ['ip' => $request->getIp()]);
return new Fluent($response->json());
}
protected function hydrate(Position $position, Fluent $location): Position
{
$position->countryCode = $location->country_code;
return $position;
}
}
Then, insert your driver class name into the configuration file:
// config/location.php
'driver' => AppLocationDriversMyDriver::class,
In version 7, the codebase has been updated with strict PHP types,
updated PHP and Laravel version requirements, an updated Driver
structure, as well as a small configuration addition.
In version 7, location drivers can now implement an Updatable
interface
that allows them to be updated using the location:update
command.
Currently, only the MaxMind driver supports this.
To update your configuration file to be able to download the latest
MaxMind database file automatically, insert the below url
configuration option in your config/location.php
file:
// config/location.php
return [
'maxmind' => [
// ...
'local' => [
// ...
+ 'url' => sprintf('https://download.maxmind.com/app/geoip_download_by_token?edition_id=GeoLite2-City&license_key=%s&suffix=tar.gz', env('MAXMIND_LICENSE_KEY')),
],
],
];
Once done, you may execute the below artisan command to download the latest .mmdb
file:
php artisan location:update
In version 7, the codebase has been updated with strict PHP
types, updated PHP and Laravel version requirements,
and an updated Driver
structure.
If you have created your own custom driver implementation,
you must update it to use the base Driver
or HttpDriver
class.
If you're fetching a location using an HTTP service, it
may be useful to extend the HttpDriver
to reduce
the code you need to write:
namespace AppLocationDrivers;
use IlluminateSupportFluent;
use StevebaumanLocationPosition;
- use StevebaumanLocationDriversDriver;
+ use StevebaumanLocationDriversHttpDriver;
- class MyDriver extends Driver
+ class MyDriver extends HttpDriver
{
- public function url($ip)
+ public function url(string $ip): string;
{
return "http://driver-url.com?ip=$ip";
}
- protected function process($ip)
- {
- return rescue(function () use ($ip) {
- $response = json_decode(file_get_contents($this->url($ip)), true);
-
- return new Fluent($response);
- }, $rescue = false);
- }
- protected function hydrate(Position $position, Fluent $location)
+ protected function hydrate(Position $position, Fluent $location): Position;
{
$position->countryCode = $location->country_code;
return $position;
}
}
Location is versioned under the Semantic Versioning guidelines as much as possible.
Releases will be numbered with the following format:
<major>.<minor>.<patch>
And constructed with the following guidelines:
Minor versions are not maintained individually, and you're encouraged to upgrade through to the next minor version.
Major versions are maintained individually through separate branches.