You are on page 1of 4

Online Store Locator using PHP, MySQL and Google Maps API

Posted on February 3, 2013 by theoryapp Where is the closest McDonalds? This tutorial shows how to build a map-based locator for finding the closest stores. We will use PHP and MySQL for the backend and JavaScript with Google Maps API for the front end.

Setup the Database


The dataset here contains geographical locations of all McDonalds in North America. It is a CSV (Comma-Separated Values) file with three columns: longitude, latitude and address. There are 15163 locations. 1-122.994495, 49.281079, 4805 E Hastings St Burnaby BC V5C 2L1 2-123.024074, 49.265642, 3695 Lougheed Hwy Vancouver BC V5M 2A6 3...... The SQL statement to create the table is as below: 1CREATE TABLE `data_mcdonalds` ( 2 `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 `lat` DOUBLE NOT NULL, 4 `lng` DOUBLE NOT NULL, 5 `address` VARCHAR(64) NOT NULL ); 6 Then we can import the data from the CSV file to the database. Note that, we need specify the column names to be lng, lat, address when importing.

Search the Closest Stores


There are two ways to search for the stores. One is to specify the central location (lat, lng) and find the closest stores based on their distance to the center. Another way is to specify a bounding box (ranges of lat and lng) and find all stores within the bound. Searching by a bounding box is easy. Suppose we have the bounding box specified by four parameters: lat0, lat1, lng0, lng1. The following query find all stores within a box. 1SELECT * 2FROM `data_mcdonalds` 3WHERE lat >= lat0 AND lat <= lat1 AND lng >= lng0 AND lng <= lng1; 4 Searching with a center requires calculating the distance. Suppose we have the center at (lat0, lng0), the following query find the closest 20 stores within 50 miles.

1 SELECT *, 2 ( 3959 * acos( cos(radians(lat0)) * cos(radians(lat)) * 3 cos(radians(lng) - radians(lng0)) + sin(radians(lat0)) * sin(radians(lat)) ) ) AS distance 4 FROM `data_mcdonalds` 5 HAVING distance < 50 6ORDER BY distance LIMIT 20; 7

Generate JSON Output


Next we use PHP to dynamically query the database and generate the result. 1 <?php 2 function die_with_error($error) { $ret = array( 3 "status" => "Failed", 4 "error" => $error 5 ); die(json_encode($ret)); 6 } 7 8 $lat = $_GET["lat"]; 9 $lng = $_GET["lng"]; 10if (!$lat || !$lng) die_with_error("invalid parameters"); 11 12 13$hostname = '111.111.111.111'; = 'xxxxxx'; 14$username $password = 'xxxxxx'; 15$dbname = 'xxx'; 16 17mysql_connect($hostname, $username, $password) or die_with_error(mysql_error()); 18 mysql_select_db($dbname) or die_with_error(mysql_error()); 19 mysql_set_charset('utf8'); 20 21$query = sprintf("SELECT *, 22 round( 3959 * acos( cos(radians(%s)) * cos(radians(lat)) * cos(radians(lng) - radians(%s)) + sin(radians(%s)) * 23 sin(radians(lat)) ), 2 ) AS distance 24 FROM `data_mcdonalds` 25 HAVING distance < 50 26 ORDER BY distance LIMIT 30;", 27 mysql_real_escape_string($lat), mysql_real_escape_string($lng), 28 mysql_real_escape_string($lat)); 29 $result = mysql_query($query); 30if (! $result) 31 die_with_error(mysql_error()); 32 33$result_array = array(); 34while ($row = mysql_fetch_assoc($result)) { array_push($result_array, array( 35 "id" => $row['id'], 36 "lat" => $row['lat'], 37 "lng" => $row['lng'], "address" => $row['address'], 38

"distance" => $row['distance'] 39 )); 40 } 41 42$ret = array( 43 "status" => "OK", "data" => $result_array); 44 die(json_encode($ret)); 45 46?> 47 48 49 50 51 52 53 54

An example output can be found using this link.

Build the Map


Next we are ready to build a map using Google Maps API. In the HTML code, we define the following elements. 1<input id="address" type="text" value="Vancouver" /> 2<input id="search" type="submit" value="Search" /> 3<div id="map_canvas" style="height: 600px; width: 800px;"> 4</div> The following is the JavaScript code. 1 var map = null; var geocoder = null; 2 var markers = []; 3 var infoWindow = null; 4 5 jQuery('#search').click(function() { var address = jQuery('#address').val() || 'Vancouver'; 6 if (map === null) 7 initializeMap(); 8 searchAddress(address); 9 }); 10 11function initializeMap() { var mapOptions = { 12 zoom: 13, 13 mapTypeId: google.maps.MapTypeId.ROADMAP 14 } map = new google.maps.Map( 15 document.getElementById('map_canvas'), mapOptions); 16 geocoder = new google.maps.Geocoder(); 17 infoWindow = new google.maps.InfoWindow(); 18} 19

20function searchAddress(address) { geocoder.geocode( { 'address': address}, 21 function(results, status) { 22 if (status === google.maps.GeocoderStatus.OK) { 23 var latlng = results[0].geometry.location; map.setCenter(latlng); 24 searchStores(latlng.lat(), latlng.lng()); 25 } else { 26 alert('Address not found: ' + status); 27 } 28 }); 29} 30 31function searchStores(lat, lng) { var url = './store-ajax.php'; 32 var parameter = { lat: lat, lng: lng }; 33 jQuery.ajax({ url: url, 34 data: parameter, 35 dataType: 'json', 36 success: showStores 37 }); 38} 39 40function showStores(data, status, xhr) { if (data['status'] != 'OK') 41 return; 42 43 infoWindow.close(); 44 for (var i = 0; i < markers.length; i++) { 45 markers[i].setMap(null); } 46 markers.length = 0; 47 48 for (var i in data['data']) { 49 createMarker(data['data'][i]); 50 } 51} 52 53function createMarker(store) { var latlng = new google.maps.LatLng( 54 parseFloat(store['lat']), 55 parseFloat(store['lng']) 56 ); var html = "<b>" + store['address'] + "</b>" + 57 store['distance'] + " miles"; 58 var marker = new google.maps.Marker({ 59 map: map, 60 position: latlng }); 61 google.maps.event.addListener(marker, 'click', function() { 62 infoWindow.setContent(html); 63 infoWindow.open(map, marker); 64 }); 65 markers.push(marker); } 66

You might also like