Most applications on the Internet are now starting to embed terrain maps.
This article is devoted to working with maps using the Google Map API.
The following describes the principles of working with the Google API, the simplest classes are implemented using SimpleXML (to many it may seem that the code is extremely simple). The terms geocoding and geocoder in the article are in English.
IntroductionGeocoding is the process of finding latitude and longitude at the entered address. Google provides free access to the developed toolkit, which can be accessed using both the JavaScript API and the web service ... This article shows how to access the geocoder web service using PHP.
There are a large number of applications for determining latitude and longitude, many of them are free. Here are some examples of how to use them:
- Drawing the address entered by the user on the map
- Using latitude and longitude for calculations (for example, finding the distance)
- Checking the address when ordering in the online store
When you use Google Maps to display maps on a site, the easiest way to use the JavaScript API, however, this is not always the best solution.
For example, if your application writes coordinates to the address that the user enters, this solution will not work for those users who have JavaScript disabled. To prevent this situation, we can use the web service to redirect all requests to the geocoder to the server.
This article will develop some classes that will help get quick access to the geocoder.
')
Getting started with Google MapsAll documentation on using the Google Maps API is located at this
address.The first thing you need to do to use the Google Maps API is to create an API key for your site. This key will identify all your requests to this API. You can get this key by agreeing to the terms of use and entering the website address on the
pageCurrently, the maximum number of requests to the geocoder is limited to 15,000 per day. But you can cache geocoder responses.
After receiving the key, you can contact the geocoder. Documentation on the use of geocoder can be found
atQuerying GeocoderWhen you make a request to a geocoder, you can specify in which format you wish to receive an answer. Available formats: JSON, XML, KML and CSV. This article describes the manipulation of the responses in XML.
KML (Keyhole Markup Data transcript) is an XML format designed for use by Google Earth. The response data in KML and XML from geocoder are identical.Although JSON is commonly used with JavaScript, we can also use it in our application. To work with JSOM using PHP, see the following
functions (starting with PHP 5.2.0). This article uses the
SimpleXML extension to process XML data from geocoder
.To request a geocoder, an HTTP request must be sent to
maps.google.com/maps/geo . The query parameters are described below:
- q - address whose coordinates must be determined
- key - the key of the Google Maps API
- output - result format (json, xml, kml or csv)
For example, to get the coordinates of the White House (located at 1600 Pennsylvania Avenue, Washington, DC), you need to make the following request:
maps.google.com/maps/geo?q=1600+ pennsylvania+ave+washington+ dc&
output=xml&key = 123456Replace 123456 with your key.The strictness of the format of the string that you send in the request is not critical, however
Parsing the answer GeocoderAfter sending a request to a geocoder, you get a response in the format that you specified. For example, if the specified address is the address of the White House, then we will receive in response the following XML document:

In this answer, we highlight 3 important elements:
- name: The address string we pass to the geocoder
- Status: The status of the response, which we can easily understand what happened. Further description of the various possible states:
- 200: Successful request (at least one place in the entered string was found)
- 400: Bad request (the server did not understand the request)
- 500: Server error (Internal error)
- 601: Missing query. The q parameter is missing or an empty string is passed.
- 602: Unknown address. No matches were found for the entered string.
- 603: Unavailable address. The address provided is missing or cannot be displayed due to legal or contractual considerations.
- 610: Invalid Google Maps API Key
- 620: Too many requests made using this key
- Placemark: If the Status field is 200, at least one Placemark element is present in the returned XML, which contains information about the transferred string.
The first useful item that is included in each placemark item is the formatted address address. This is very important, as users can enter the same address differently. If you look at the example above, you can see that the string “1600 pennsylvania ave washington dc” was entered for the search, and “1600 Pennsylvania Ave NW, Washington, DC 20006, USA” was received as an answer.
The next element is AddressDetails, which uses Extensible Address Language (xAL) to provide information. This element has an Accuracy attribute that indicates the degree of accuracy of the positioning. Possible values for the Accuracy attribute:
- 0: Unknown
- 1: Country
- 2: Region
- 3: Sub-region
- 4: Town
- 5: Postcode
- 6: Street
- 7: Intersection
- 8: Address
In the example above, the attribute value is 8, which indicates the highest level of accuracy.
Other elements inside the AddressDetails element describe parts of the found space in accordance with the xAL language specification.
Each placemark element contains a Point element. This element contains data separated by commas. The first element is longitude; the second is latitude; the third argument is altitude above sea level (not used).
Access Geocoder data using SimpleXML
To parse the resulting XML, we will use SimpleXML, an extension that makes working with XML in PHP quite easy. SimpleXML is built into PHP, starting with PHP 5.
To read XML data, you need to initialize the SimpleXMLElement object, passing to its constructor the XML string that we want to parse.
$ str = "XML string"; // sample XML file
$ xml = new SimpleXMLElement ($ str);
By creating an object of the SimpleXMLElement class, we can access all elements of the XML string as if they were ordinary properties of the object. For example, you can get access to the response status using the following code:
$ xml = new SimpleXMLElement ($ geocoderResponse);
echo $ xml-> Response-> Status-> code;
It should be noted that the type $ xml-> Response-> Status-> code is SimpleXMLElement. Therefore, it is necessary to use to cast types to a string or number.
$ xml = new SimpleXMLElement ($ geocoderResponse);
$ status = (int) $ xml-> Response-> Status-> code;
if ($ status == 200) {...}
We now know how to read XML data, but some elements contain attributes. The following example shows how to access these attributes.
$ xml = new SimpleXMLElement ($ geocoderResponse);
foreach ($ xml-> Response-> Placemark as $ placemark) {
$ accuracy = (int) $ placemark-> AddressDetails ['Accuracy'];
($ accuracy == 8) {...}
}
Creating a Geocoder Class
This article will discuss the implementation of a solution for the use of information from Google geocoder. The process will consider writing three classes:
- Geocoder: This class will be used to work with geocoder (sending requests, receiving and parsing answers).
- Placemark: This class will contain the places returned by the geocoder.
- Point: The coordinates of the places found will be in this class.
We proceed to the implementation of the class Geocoder. This class will contain the lookup () method, whose input will be the address to search for, and the result will be an array of Placecmark class elements with the found places.
The code below shows part of the class implementation. First, the geocoder address is determined. We determine the required number of constants corresponding to the return status. Using constants makes the code more readable and supported. For consistency, we use the same constants as defined for the
JavaScript API.class Geocoder
{
public static $ url = 'http://maps.google.com/maps/geo';
const G_GEO_SUCCESS = 200;
const G_GEO_BAD_REQUEST = 400;
const G_GEO_SERVER_ERROR = 500;
const G_GEO_MISSING_QUERY = 601;
const G_GEO_MISSING_ADDRESS = 601;
const G_GEO_UNKNOWN_ADDRESS = 602;
const G_GEO_UNAVAILABLE_ADDRESS = 603;
const G_GEO_UNKNOWN_DIRECTIONS = 604;
const G_GEO_BAD_KEY = 610;
const G_GEO_TOO_MANY_QUERIES = 620;
protected $ _apiKey;
public function __construct ($ key)
{
$ this -> _ apiKey = $ key;
}
}
As described above, we implement the lookup () method, which returns an array of Placemark objects. To get a response from a geocoder, we will write a method called performRequest ().
The performRequest () method will take the address string as the first argument and the type of data returned as the second argument.
This method uses Curl functions to make HTTP requests. To receive responses from the server, the CURLOPT_RETURNTRANSFER parameter must be set to true.
class Geocoder
{
public function performRequest ($ search, $ output = 'xml')
{
$ url = sprintf ("% s? q =% s & output =% s & key =% s & oe = utf-8", self :: $ url, urlencode ($ search), $ output, $ this -> _ apiKey);
$ ch = curl_init ($ url);
curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, true);
$ response = curl_exec ($ ch);
curl_close ($ ch);
return $ response;
}
}
Now we will closely deal with the implementation of the lookup () method. At the beginning we will receive a response from the server using the performRequest () method, create an object of the SimpleXMLELement class. Next we read the request status returned by the server. The singular of the normal request will be the status G_GEO_SUCCESS, G_GEO_UNKNOWN_ADDRESS or G_GEO_UNAVAILABLE_ADDRESS. The last two values will show that the specified places were not found, in this case an empty array will be returned.
If the status code is G_GEO_SUCCESS, we will process the found places in a loop and create objects for the Placemark type for each ... We will write the FromSimpleXml () method to create an object of the Placemark class.
For all other status codes, we will create an exception.
class Geocoder
{
public function lookup ($ search)
{
$ response = $ this-> performRequest ($ search, "xml");
$ xml = new SimpleXMLElement ($ response);
$ status = (int) $ xml-> Response-> Status-> code;
switch ($ status)
{
case self :: G_GEO_SUCCESS:
require_once ("Placemark.php");
$ placemarks = array ();
foreach ($ xml-> Response-> Placemark as $ placemark)
$ placemarks [] = Placemark :: FromSimpleXml ($ placemark);
return $ placemarks;
case self :: G_GEO_UNKNOWN_ADDRESS:
case self :: G_GEO_UNAVAILABLE_ADDRESS:
return array ();
default:
throw new Exception (sprintf ("Google Geo error% d occurred", $ status));
}
}
}
This is the complete code for the Geocoder class. If you want to use the performRequest () function, you can do it, but now you need to implement the Placemark class before using the lookup () method.
require_once ("Geocoder.php");
$ address = "1600 Pennsylvania Ave Washington DC";
$ geocoder = new Geocoder ('your key');
$ xml = $ geocoder-> performRequest ($ address, "xml");
$ json = $ geocoder-> performRequest ($ address, "json");
$ csv = $ geocoder-> performRequest ($ address, "csv");
Creating a Placemark ClassWe are now implementing the Placemark class, which will be used to store location information. It is preferable to save all the parts of the address returned from the geocoder, of course, we restrict ourselves to the preservation of three elements:
- Latitude and longitude of the place (using the class Point)
- Formatted address returned from geocoder
- Location accuracy
To implement this class, we write the set and get functions (setPoint (), getPoint (), setAddress (), getAddress (), setAccuracy (), and getAccuracy () functions). We also implement the static FromSimpleXml () method, which is used in the Geocoder class.
In the Placemark class, we define constants responsible for the accuracy of positioning. For example, to determine whether only a country is defined, use the following
if ($ placemark-> getAccuracy () == Placemark :: ACCURACY_COUNTRY) {...}
Implementation.
class Placemark
{
const ACCURACY_UNKNOWN = 0;
const ACCURACY_COUNTRY = 1;
const ACCURACY_REGION = 2;
const ACCURACY_SUBREGION = 3;
const ACCURACY_TOWN = 4;
const ACCURACY_POSTCODE = 5;
const ACCURACY_STREET = 6;
const ACCURACY_INTERSECTION = 7;
const ACCURACY_ADDRESS = 8;
protected $ _point;
protected $ _address;
protected $ _accuracy;
}
The Google Maps API does not define named constants for accuracy.Next comes the definition of so-called setters and getters, I miss the author’s comments.class Placemark
{
// other code
public function setAddress ($ address)
{
$ this -> _ address = (string) $ address;
}
public function getAddress ()
{
return $ this -> _ address;
}
public function __toString ()
{
return $ this-> getAddress ();
}
public function setPoint (Point $ point)
{
$ this -> _ point = $ point;
}
public function getPoint ()
{
return $ this -> _ point;
}
public function setAccuracy ($ accuracy)
{
$ this -> _ accuracy = (int) $ accuracy;
}
public function getAccuracy ()
{
return $ this -> _ accuracy;
}
// other code
}
In the end, we will implement the FromSimpleXml () method, which is a factory method for creating Placemark objects based on the SimpleXMLElement object.
In the example described below, the Point class and its Create () method are used, they will be described below.
class Placemark
{
// other code
public static function FromSimpleXml ($ xml)
{
require_once ('Point.php');
$ point = Point :: Create ($ xml-> Point-> coordinates);
$ placemark = new self;
$ placemark-> setPoint ($ point);
$ placemark-> setAddress ($ xml-> address);
$ placemark-> setAccuracy ($ xml-> AddressDetails ['Accuracy']);
return $ placemark;
}
}
Creating a Point ClassThe last class to be implemented for full use is the class Point. This class stores latitude and longitude. This data is transmitted in the constructor, there are also methods for obtaining the values of latitude and longitude.
class point
{
protected $ _lat;
protected $ _lng;
public function __construct ($ latitude, $ longitude)
{
$ this -> _ lat = $ latitude;
$ this -> _ lng = $ longitude;
}
public function getLatitude ()
{
return $ this -> _ lat;
}
public function getLongitude ()
{
return $ this -> _ lng;
}
public static function Create ($ str)
{
list ($ longitude, $ latitude, $ elevation) = explode (',', $ str, 3);
return new self ($ latitude, $ longitude);
}
}
ConclusionThis article describes the simplest algorithm for working with geocoder using Google Maps. You can also use these classes together with JavaScript, but you should also not forget that not everyone can have JavaScript turned on.
Also, keep in mind that caching geocoder responses will allow you to reduce workload and increase performance in the future.
Links