Skip to content

Instantly share code, notes, and snippets.

@olivertappin
Created December 9, 2018 21:20
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 olivertappin/f25e74e3e09560e7d7f59f898d234744 to your computer and use it in GitHub Desktop.
Save olivertappin/f25e74e3e09560e7d7f59f898d234744 to your computer and use it in GitHub Desktop.
Postcode Lookup using the Google Geocoding API
<?php
namespace App\Http\Controllers\Api;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller as BaseController;
use Illuminate\Http\Response;
use App\Mappers\Response\Address as AddressMapper;
class PostcodeLookupController extends BaseController
{
/**
* @param Request $request
* @param Client $client
* @return \Illuminate\Http\JsonResponse
*/
public function address(Request $request, Client $client)
{
$postcode = $request->query('postcode');
if (null === $postcode) {
return response()->json(
['errorMessage' => 'Please enter a postcode.'],
Response::HTTP_UNPROCESSABLE_ENTITY
);
}
if (!is_string($postcode)) {
return response()->json(
['errorMessage' => 'Please enter a valid postcode.'],
Response::HTTP_UNPROCESSABLE_ENTITY
);
}
$postcode = preg_replace('/[^A-Z0-9 ]/', '', strtoupper($postcode));
$key = config('app.api.keys.google_cloud');
$response = $client->get(
'https://maps.googleapis.com/maps/api/geocode/json?' . http_build_query([
'address' => urlencode($postcode),
'key' => $key,
])
);
$body = json_decode($response->getBody()->getContents(), true);
if (empty($body['results'])) {
return response()->json(
['errorMessage' => 'Unable to get lat and lng from postcode.'],
Response::HTTP_UNPROCESSABLE_ENTITY
);
}
$lat = $body['results'][0]['geometry']['location']['lat'];
$lng = $body['results'][0]['geometry']['location']['lng'];
$response = $client->get(
'https://maps.googleapis.com/maps/api/geocode/json?' . http_build_query([
'latlng' => $lat . ',' . $lng,
'key' => $key,
])
);
$body = json_decode($response->getBody()->getContents(), true);
if (empty($body['results'])) {
return response()->json(
['errorMessage' => 'Unable to get address components from lat and lng.'],
Response::HTTP_UNPROCESSABLE_ENTITY
);
}
$apiResponse = [];
foreach ($body['results'] as $i => $result) {
$addressData = $result['address_components'];
foreach ($addressData as $data) {
$apiResponse[$i][$data['types'][0]] = $data['long_name'];
}
}
$response = [
'latitude' => $lat,
'longitude' => $lng,
'addresses' => [],
];
foreach ($apiResponse as $i => $address) {
$mappedAddress = AddressMapper::map($address);
if (empty($mappedAddress['postcode'])) {
continue;
}
$response['addresses'][$i] = [
'text' => implode(', ', array_filter($mappedAddress)),
'parts' => $mappedAddress,
];
}
return response()->json($response);
}
}
// ...
namespace App\Mappers\Response;
interface MapperInterface
{
/**
* @param array $raw
* @return array
*/
public function map(array $raw);
}
class Address implements MapperInterface
{
/**
* @param array $raw
* @return array
*/
public function map($raw)
{
$response = [
'subdivision' => '',
'address' => '',
'town' => '',
'county' => '',
'postcode' => '',
];
if (isset($raw['premise'])) {
$response['subdivision'] = $raw['premise'];
}
if (isset($raw['street_number'])) {
$response['address'] = $raw['street_number'];
}
if (isset($raw['route']) && 'Unnamed Road' !== $raw['route']) {
if ('' !== $response['address']) {
$response['address'] .= ' ';
}
$response['address'] .= $raw['route'];
}
if (isset($raw['postal_town'])) {
$response['town'] = $raw['postal_town'];
}
if (isset($raw['administrative_area_level_2'])) {
$response['county'] = $raw['administrative_area_level_2'];
}
if (isset($raw['postal_code'])) {
$response['postcode'] = $raw['postal_code'];
}
return $response;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment