Geocode An Address With Google Maps
Part 16 of 48 in API Driven Development With Laravel and VueJSA nifty feature that will open up a lot of doors for functionality is the ability to have our Cafe’s address in a latitude and longitude format. This process is called Geocoding. There are a lot of services that offer Geocoding services such as Geocodio Geocodio — Simply affordable geocoding — Home and Google Maps. We will be using Google Maps to geocode an address.
In the last tutorial, we validated a new cafe upon submission to our API Validating an API Request with Javascript and Laravel. This tutorial will be building on the data that we got validated. Since all cafes have an address, we will be using that address to find the latitude and longitude. We can then run distance analysis, local cafes, plot on a map, etc.
Before we begin, the documentation we will be using can be found here: Developer’s Guide | Google Maps Geocoding API | Google Developers. Since we are getting the latitude and longitude AFTER submission, we will be using PHP to make the request. The reason we are doing the geocoding after the submission is we have the final data and don’t have to do multiple calls to the geocoding service. Google does charge for GeoCoding service and you can find out which plan suits you best here: https://developers.google.com/maps/pricing-and-plans/
Step 1: Get a Google Maps API Key
You will need an API key before you can make calls to the Google Maps Geocoding service.
First you will have to visit: Get API Key | Google Maps Geocoding API | Google Developers
Next, find the link to get a key.
Once you click on that link, a modal window will appear and you will select your project to enable the API. If you need to, you can create a project as well.
Your key will be displayed in the modal once it’s created.
Step 2: Add the Key to Your .env file
Since we are calling the Google Maps API with PHP in a Laravel install, we can store the Google Maps Key in our .env file. This is just for safe keeping and makes it easy to maintain.
The entry I’m using is:
GOOGLE_MAPS_KEY={KEY}
Step 3: Build Google Maps Utility
Since we have our key, it’s time to build our geocoding request. Since there could be other places to reuse this, I usually build a utility object to run this method.
First, create an app\Utilities
directory.
Next, add a file app\Utilities\GoogleMaps.php
which is the GoogleMaps utility and don’t forget to namespace it. Our file should look like:
<?php
namespace App\Utilities;
class GoogleMaps{
}
We now have a GoogleMaps utility that we can put some methods in that we may need to use later.
Step 4: Make sure Guzzle HTTP is installed
If you already have Guzzle installed on Laravel, you can skip this step. If you don’t want to use Guzzle, you can also skip this step. I love using Guzzle because it makes making PHP HTTP requests phenomenally easy: Guzzle, PHP HTTP client — Guzzle Documentation . The methods are chain able and make way more sense than remembering all of the curl parameters.
To install guzzle, run:
composer require guzzlehttp/guzzle:~6.0
Guzzle is now installed on your Laravel system!
Step 5: Add a Geocode method to the Google Maps Utility
First we will add a static method to our utility with the signature to accept the parameters returned from the Google Maps API:
/*
Geocodes an addres so we can get the latitude and longitude
*/
public static function geocodeAddress( $address, $city, $state, $zip ){
}
Next we need to define our variables and run our Guzzle command and return the values. Our method should look like this:
/*
Geocodes an addres so we can get the latitude and longitude
*/
public static function geocodeAddress( $address, $city, $state, $zip ){
/*
Builds the URL and request to the Google Maps API
*/
$url = 'https://maps.googleapis.com/maps/api/geocode/json?address='.urlencode( $address.' '.$city.', '.$state.' '.$zip ).'&key='.env( 'GOOGLE_MAPS_KEY' );
/*
Creates a Guzzle Client to make the Google Maps request.
*/
$client = new \GuzzleHttp\Client();
/*
Send a GET request to the Google Maps API and get the body of the
response.
*/
$geocodeResponse = $client->get( $url )->getBody();
/*
JSON decodes the response
*/
$geocodeData = json_decode( $geocodeResponse );
/*
Initializes the response for the GeoCode Location
*/
$coordinates['lat'] = null;
$coordinates['lng'] = null;
/*
If the response is not empty (something returned),
we extract the latitude and longitude from the
data.
*/
if( !empty( $geocodeData )
&& $geocodeData->status != 'ZERO_RESULTS'
&& isset( $geocodeData->results )
&& isset( $geocodeData->results[0] ) ){
$coordinates['lat'] = $geocodeData->results[0]->geometry->location->lat;
$coordinates['lng'] = $geocodeData->results[0]->geometry->location->lng;
}
/*
Return the found coordinates.
*/
return $coordinates;
}
You can see in the URL, we are using the JSON endpoint so we can run the json_decode
command on the response returned. We then initialize an array to be returned with the lat
and lng
keys set to null initially.
Next we check to see if something was returned from the API. For more information on the response signature from Google Maps’ Geocoding Service, check out: Developer’s Guide | Google Maps Geocoding API | Google Developers
We just want to see if there is data, not zero results, and that each array key we need is set. This way we can access geometry we need that is returned.
If everything is good to go, we set the coordinates array with the latitude and longitude and return the coordinates. Now we can simply GeoCode any address that gets sent into our system!
Step 6: Add Latitude and Longitude to Cafe Creation
We are now ready to GeoCode our new Cafe route! When we created our Cafes migration in: Add Laravel API End Points – Server Side Up. We left space for a latitude and longitude field, so we are ready to rock and roll when it comes to saving the latitude and longitude returned.
First, open the /app/Http/Controllers/API/CafesController.php
.
On top of the file, declare that we will be using the GoogleMaps utility:
use App\Utilities\GoogleMaps;
Next, find the postNewCafe()
method and add the following code before we create the new Cafe:
/*
Get the Latitude and Longitude returned from the Google Maps Address.
*/
$coordinates = GoogleMaps::geocodeAddress( $request->get('address'), $request->get('city'), $request->get('state'), $request->get('zip') );
What this does is pass in the data we received from the request (and validated 😉 ) and gets the latitude and longitude.
Now we need to take what’s returned from the method, and add it to our new cafe so our updated postNewCafe()
method will look like:
/*
|-------------------------------------------------------------------------------
| Adds a New Cafe
|-------------------------------------------------------------------------------
| URL: /api/v1/cafes
| Method: POST
| Description: Adds a new cafe to the application
*/
public function postNewCafe( StoreCafeRequest $request ){
/*
Get the Latitude and Longitude returned from the Google Maps Address.
*/
$coordinates = GoogleMaps::geocodeAddress( $request->get('address'), $request->get('city'), $request->get('state'), $request->get('zip') );
$cafe = new Cafe();
$cafe->name = $request->get('name');
$cafe->address = $request->get('address');
$cafe->city = $request->get('city');
$cafe->state = $request->get('state');
$cafe->zip = $request->get('zip');
$cafe->latitude = $coordinates['lat'];
$cafe->longitude = $coordinates['lng'];
$cafe->save();
return response()->json($cafe, 201);
}
We take the data returned from the Google Maps API and add it to the new cafe we are creating. Now we have a fully functioning GeoCode call coming through and we can use the coordinates later on when we need to map, or query by location!
Conclusion
This was a real quick example on how to Geocode an address. There’s a lot of useful data that gets returned from the Google Maps API Developer’s Guide | Google Maps Geocoding API | Google Developers so feel free to mess around with some of that data as well. If you have any questions, feel free to ask or post a comment below! All source code is available here: GitHub – serversideup/roastandbrew