Skip to content

Instantly share code, notes, and snippets.

@randy-allen
Created June 12, 2019 20:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save randy-allen/fb6e4b3882804dc9a63514b504999e15 to your computer and use it in GitHub Desktop.
Save randy-allen/fb6e4b3882804dc9a63514b504999e15 to your computer and use it in GitHub Desktop.
A version of spatie/geocoder that uses dev.virtualearth.net instead of Google Maps API
<?php
namespace Spatie\Geocoder;
use GuzzleHttp\Client;
use Spatie\Geocoder\Exceptions\CouldNotGeocode;
class Geocoder
{
const RESULT_NOT_FOUND = 'result_not_found';
/** @var \GuzzleHttp\Client */
protected $client;
/** @var string */
// protected $endpoint = 'https://maps.googleapis.com/maps/api/geocode/json';
protected $endpoint = 'http://dev.virtualearth.net/REST/v1/Locations';
/** @var string */
protected $apiKey;
/** @var string */
protected $language;
/** @var string */
protected $region;
/** @var string */
protected $bounds;
/** @var string */
protected $country;
public function __construct(Client $client)
{
$this->client = $client;
}
public function setApiKey(string $apiKey)
{
$this->apiKey = $apiKey;
return $this;
}
public function setLanguage(string $language)
{
$this->language = $language;
return $this;
}
public function setRegion(string $region)
{
$this->region = $region;
return $this;
}
public function setBounds(string $bounds)
{
$this->bounds = $bounds;
return $this;
}
public function setCountry(string $country)
{
$this->country = $country;
return $this;
}
public function getCoordinatesForAddress(string $address): array
{
if (empty($address)) {
return $this->emptyResponse();
}
$payload = $this->getRequestPayload(['query' => $address]);
$response = $this->client->request('GET', $this->endpoint, $payload);
if ($response->getStatusCode() !== 200) {
throw CouldNotGeocode::couldNotConnect();
}
$geocodingResponse = json_decode($response->getBody());
if (! empty($geocodingResponse->error_message)) {
throw CouldNotGeocode::serviceReturnedError($geocodingResponse->error_message);
}
if (! count($geocodingResponse->resourceSets)) {
return $this->emptyResponse();
}
return $this->formatResponse($geocodingResponse);
}
public function getAddressForCoordinates(float $lat, float $lng): array
{
$payload = $this->getRequestPayload([
'latlng' => "$lat,$lng",
]);
$response = $this->client->request('GET', $this->endpoint, $payload);
if ($response->getStatusCode() !== 200) {
throw CouldNotGeocode::couldNotConnect();
}
$reverseGeocodingResponse = json_decode($response->getBody());
if (! empty($reverseGeocodingResponse->error_message)) {
throw CouldNotGeocode::serviceReturnedError($reverseGeocodingResponse->error_message);
}
if (! count($reverseGeocodingResponse->results)) {
return $this->emptyResponse();
}
return $this->formatResponse($reverseGeocodingResponse);
}
protected function formatResponse($response): array
{
return [
'lat' => $response->resourceSets[0]->resources[0]->point->coordinates[0],
'lng' => $response->resourceSets[0]->resources[0]->point->coordinates[1],
'accuracy' => $response->resourceSets[0]->resources[0]->confidence,
'formatted_address' => $response->resourceSets[0]->resources[0]->name,
'viewport' => $response->resourceSets[0]->resources[0]->geocodePoints,
// 'address_components' => $response->results[0]->address_components,
// 'place_id' => $response->results[0]->place_id,
];
}
protected function getRequestPayload(array $parameters): array
{
$parameters = array_merge([
'key' => $this->apiKey,
// 'language' => $this->language,
// 'region' => $this->region,
// 'bounds' => $this->bounds,
], $parameters);
if ($this->country) {
$parameters = array_merge(
$parameters,
['components' => 'country:'.$this->country]
);
}
return ['query' => $parameters];
}
protected function emptyResponse(): array
{
return [
'lat' => 0,
'lng' => 0,
'accuracy' => static::RESULT_NOT_FOUND,
'formatted_address' => static::RESULT_NOT_FOUND,
'viewport' => static::RESULT_NOT_FOUND,
];
}
}
@randy-allen
Copy link
Author

This file goes in /vendor/spatie/geocoder/src

Still requires a GOOGLE_MAPS_GEOCODING_API_KEY= in your .env file that is actually your API key from dev.virtualearth.net

TODO:
Fork spatie/geocoder and do this properly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment