How to Code a Simple Zip Code Locator in PHP

That’s all there is to it. I hope this has shown you how easy it is to code a simple zip code locator. Below is the code in it’s entirety, and you can see an example here. The End

<html>
<head>
<script type="text/javascript"
src="http://maps.yahooapis.com/v3.5/fl/javascript/apiloader.js?&appid=PASTE YOUR API KEY HERE">
</script>
<style type="text/css">
#mapContainer{
  height: 400px;
  width: 400px;
	border:1px solid #333;
}
</style>
</head>
<body>
<p>Enter your 5 digit zip code:</p>
<form name="locate" method="POST"
    action="<?=$_SERVER['PHP_SELF']?>">
<input name="zip" maxlength="5" size="6" type="text" />
<input type="submit" value="Find" />
</form>

<?php
// see if our zip code has been posted, and if it is a 5 digit #
if (isset($_POST['zip'])) {

  // remember to sanitize your inputs
  // this removes whitespace around the data and the next line makes sure its a 5 digit number
  $findzip = trim($_POST['zip']);
  if (preg_match("#^\d{5}$#",$findzip)) {

    // if we have the right kind of data, connect to the database
    $conn = mysql_connect('[[localhost]]','[[databse-user]]','[[database-password]]');

    // select the database with the tables we created in step 3
    mysql_select_db('[[database-name]]',$conn);

    // create a query that will select the zip code (if we can't find the user entered zip, we return an error)
    $query = "SELECT latitude,longitude,state,city FROM zip_codes WHERE zip=".$findzip." LIMIT 1";
    $result = mysql_query($query);
    if (mysql_num_rows($result) > 0) {

      // grab the latitude, longitude,state and city from our result
      list($flat,$flon,$fstate,$fcity) =  mysql_fetch_row($result);

      // now get all stores in the same state, or all stores if no states match
      // we want to reduce the amount of work the database has to do so we see if a state matches
      $query = "SELECT * FROM stores WHERE state='".$fstate."'";
      $result = mysql_query($query);
      if (mysql_num_rows($result) < 1) {
        $query = "SELECT * FROM stores";
        $result = mysql_query($query);
      }

      // now we process the stores to gather their data,
      //this result should not be empty, so I was lazy and didn't write an else case
      if (mysql_num_rows($result) > 0) {
        while($row = mysql_fetch_assoc($result)) {

          // first put all of the data for this store into an array, with the store id as the key
          $storeinfo[$row['id']] = $row;

          // get the store zip
          $dzip = $row['zip'];

          // query for the store's latitude and longitude
          $query = "SELECT latitude,longitude FROM zip_codes WHERE zip=".$dzip." LIMIT 1";
          $result2 = mysql_query($query);
          if (mysql_num_rows($result2) > 0) {
            list($dlat,$dlon) =  mysql_fetch_row($result2);

            // now get the distance from the user entered zip
            // this function can be found on the same site as the one where you downloaded the zip codes from
            $stores[$row['id']] = calcDist($flat,$flon,$dlat,$dlon);
          }
        }
      }

      // compare the distances (by sorting them least to greatest) to find the least
      asort($stores);

      // now we can display closest store
      // optionally you could loop over this to list multiple stores
      $store = $storeinfo[key($stores)];

      // here is the lazy way to print out the data - I leave the pretty printing up to you
      print_r($store);

      // we'll need this variable for the Yahoo Maps integration
      $maploc = $store['address1'] .", ".$store['city']." ".$store['state']." ".$store['zip'];
?>

<div id="mapContainer"></div>

<script>

// this is the address we want to map (you can list several and it will mark each one)
var addresses = new Array("<?=$maploc?>");

// Create and display Map object at the address with zoom level 3
// Include your application ID.
var map = new Map("mapContainer", "PASTE YOUR API KEY HERE", "<?=$maploc?>", 3);
map.addEventListener(Map.EVENT_INITIALIZE, onMapInit);
map.addEventListener(Map.EVENT_MARKER_GEOCODE_SUCCESS,onMarkerGeocode);
function onMapInit(eventObj) {
map.addTool( new PanTool(), true );
for(var i=0; i<addresses .length; i++) {

// if you did do multiple addresses, then this would have to change some (because it would be the same store each iteration)
var marker = new CustomPOIMarker('<?php echo str_replace("'","\'",$store['company']); ?>', '', '<?=$store['address1']?><br /><?=$store['city']?> <?=$store['state']?>, <?=$store['zip']?>', '0x000000', '0xFFFFFF');
map.addMarkerByAddress( marker, addresses[i] );
}
map.addWidget( new ZoomBarWidget() );
}
function onMarkerGeocode(eventObj) {
var geocodeResponse = eventObj.response;
}
</script>

<?php
    }
    //if can't find zip return error
    else {
      printError("The zip code you entered was not found in our database.  Please try another one.");
    }

  } else {
    printError("The zip code must be a 5 digit number. Please try again.");
  }
} else {
  //do nothing
}

// functions
function printError($e)
{
  echo "<p class='error'>$e";
}
function calcDist($lat_A, $long_A, $lat_B, $long_B)
{
  $distance = sin(deg2rad($lat_A))
                * sin(deg2rad($lat_B))
                + cos(deg2rad($lat_A))
                * cos(deg2rad($lat_B))
                * cos(deg2rad($long_A - $long_B));
  $distance = (rad2deg(acos($distance))) * 69.09;
  return $distance;
}
?>
</body>
</html>

Pages: 1 2 3 4 5

if you liked this post :)

Category: Programming | 15,462 views | Posted: October 22nd 2007 07:00 am

Related Posts

5 Comments »

MyAvatars 0.2

Comment by James Ehly
on 22 Oct 2007 at 9:42 am #

Well I just figured out a logical error in the script. If you find by state first then that might not actually be the closest location to you (since there might be a closer location in the state next to you). Just comment out the lines about querying the state first and you should be fine. However, I assume doing this will slow the code down quite a bit if you have a ton of locations to search against. Maybe caching the queries somehow would be in order.

James

 

[...] spam and web stats: Usi…How to Code a Simple Zip Code Loc…WPA Can also be Cracked!!…Out sick: Preparing for a regular…Getting Technorati Authority [...]

 
MyAvatars 0.2

Comment by Internet Television
on 24 Jan 2008 at 4:16 pm # Subscribed to comments via email

That’s absolutely beautiful, great work.

 
MyAvatars 0.2

Comment by josh
on 01 May 2008 at 8:17 am #

What do i have to do to show more stores?

MyAvatars 0.2

Comment by James Ehly
on 01 May 2008 at 8:44 am #

A few people have asked me this, so here is the looping code you’ll need.

Find this line and add some code like this…

// now we can display closest store
// optionally you could loop over this to list multiple stores
$store = $storeinfo[key($stores)];
print "<p>The web developers closest to: $findzip</p><br>\n";
$maploc = "’You are here’,'$findzip’,";
foreach($stores as $k=>$v) {
$output .= "<h3 style=’margin:0;padding:0′><b>".$info[$k]['company']."</b><br>(approx ".round($v)." miles)</h3>";
$output .= "<p style=’margin:0 0 10px 0;padding:0′><a href=’".$info[$k]['url']."’>".$info[$k]['url']."</a><br>";
$output .= $info[$k]['city']." ".$info[$k]['state'].", ".$info[$k]['zip']."</p>";
$maploc .= "’".$info[$k]['company']."’,'".$info[$k]['address1']." ".$info[$k]['city']." ".$info[$k]['state']." ".$info[$k]['zip']."’,";
}
$maploc = substr($maploc,0,-1);

And here are the changes to the javascript:

<script>
// this is the address we want to map (you can list several and it will mark each one)
var addresses = new Array(<?=$maploc?>);
// Create and display Map object at the address with zoom level 3
// Include your application ID.
var map = new Map("mapContainer", "[your api key here]", "<?=$maploc?>",20);
map.addEventListener(Map.EVENT_INITIALIZE, onMapInit);
map.addEventListener(Map.EVENT_MARKER_GEOCODE_SUCCESS,onMarkerGeocode);
function onMapInit(eventObj) {
map.addTool( new PanTool(), true );
for(var i=0; i<addresses.length; i=i+2) {
//alert(addresses[i]);
//alert(addresses[i+1]);
// if you did do multiple addresses, then this would have to change some (because it would be the same store each iteration)
var marker = new CustomPOIMarker(addresses[i], ”, addresses[i+1], ‘0×000000′, ‘0xFFFFFF’);
map.addMarkerByAddress( marker, addresses[i+1] );
}
map.addWidget( new ZoomBarWidget() );
}
function onMarkerGeocode(eventObj) {
var geocodeResponse = eventObj.response;
}
</script>

Basically what you are doing is building an array of results and looping over then with the javascript.

Hope this helps. James

 
 
Name (required)
E-mail (required - never shown publicly)
URI
Subscribe to comments via email
Your Comment (smaller size | larger size)
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> in your comment.

« Links from the Trench #8 | Did You Pass the BlogRush Test? »