DomerBill
asked on
Zip radius search
I am making a website that allows users to search suppliers in my product database. I want to have a zip radius search function to narrow down the results to a more meaningful level.
I copied from online free codes demo.php and zipcode.php and made a test page Radius.html. By trial, these three files seem work fine together. I can get a list of zip codes from my database that are within the range I specified in the Radius.html.
when it comes to integrate the scripts to my actual search page Home2.html and results page Results2.php, I am totally lost as a layman to PHP/MySql coding and newbie to Dreamweaver (I am using Dreamweaver CS3).
Any help would be highly appreciated. I have enclosed the srcipts of the five files I mentioned above.
1. Radius.html
<div id="mainContent">
  <form id="form2" name="form2" method="post" action="demo.php">
   Within a
   radius of
   <label>
   <select name="Radius" id="Radius">
    <option value="50">50</option>
    <option value="100" selected="selected">100</o ption>
    <option value="150">150</option>
    <option value="200">200</option>
    <option value="250">250</option>
    <option value="300">300</option>
   </select>
   </label>
   miles from
   <label>Destination Zip
   <input name="Destination" type="text" id="Destination" maxlength="7" />
   </label>
   <p>
2. demo.php
<?php
/* Â
  DEMO for using the zipcode PHP class. By: Micah Carrick
  Questions?  Comments?  Suggestions?  email@micahcarrick.com
*/
require_once('zipcode.php' ); Â Â Â // zip code class
// Open up a connection to the database. Â The sql required to create the MySQL
// tables and populate them with the data is in the /sql subfolder. Â You can
// upload those sql files using phpMyAdmin or a MySQL prompt. Â You will have to
// modify the below information to your database information. Â
mysql_connect('localhost', 'user','pw d') or die(mysql_error());
mysql_select_db('db') or die(mysql_error());
// Below is an example of how to calculate the distance between two zip codes.
$Radius = $_POST['Radius'];
$Destination = $_POST['Destination'];
echo '<h3>zip codes withing the radius of your destination</h3>';
$z = new zipcode_class;
$zips = $z->get_zips_in_range($Des tination, $Radius, _ZIPS_SORT_BY_DISTANCE_ASC , true);
if ($zips === false) echo 'Error: '.$z->last_error;
else {
 Â
  foreach ($zips as $key => $value) {
   echo "Zip code <b>$key</b> is <b>$value</b> miles away from <b>'$Destination'</b>.<br />";
  }
 Â
  // One thing you may want to do with this is create SQL from it. For example,
  // iterate through the array to create SQL that is something like:
  // WHERE zip_code IN ('93001 93002 93004')
  // and then use that condition in your query to find all pizza joints or
  // whatever you're using it for. Make sense? Hope so.
 Â
  echo "<br /><i>get_zips_in_range() executed in <b>".$z->last_time."</b> seconds.</i><br />";
}
// And one more example of using the class to simply get the information about
// a zip code. Â You can then do whatever you want with it. Â The array returned
// from the function has the database field names as the keys. Â I just do a
// couple string converstions to make them more readable.
echo '<h3>details about your destination</h3>';
$Destination = $_POST['Destination'];
$details = $z->get_zip_details($Desti nation);
if ($details === false) echo 'Error: '.$z->last_error;
else {
  foreach ($details as $key => $value) {
   $key = str_replace('_',' ',$key);
   $key = ucwords($key);
   echo "$key: $value<br />";
  }
}
?>
3. zipcode.php
<?php
/************************* ********** ********** ********** ********** ********** ****
 *         ZIP Code and Distance Claculation Class
 ************************** ********** ********** ********** ********** ********** ***
 *    Author:   Micah Carrick
 *    Email:    email@micahcarrick.com
 *    Website:   http://www.micahcarrick.com
 *
 *    File:    zipcode.class.php
 *    Version:   1.2.0
 *    Copyright:  (c) 2005 - Micah Carrick
 *          You are free to use, distribute, and modify this software
 *          under the terms of the GNU General Public License.  See the
 *          included license.txt file.
 *
 ************************** ********** ********** ********** ********** ********** ***
 *  VERION HISTORY:
 *    v1.2.0 [Oct 22, 2006] - Using a completely new database based on user
                contributions which resolves many data bugs.
               - Added sorting to get_zips_in_range()
               - Added ability to include/exclude the base zip
                from get_zips_in_range()
              Â
 *    v1.1.0 [Apr 30, 2005] - Added Jeff Bearer's code to make it MUCH faster!
Â
 *    v1.0.1 [Apr 22, 2005] - Fixed a typo :)
Â
 *    v1.0.0 [Apr 12, 2005] - Initial Version
 *
 ************************** ********** ********** ********** ********** ********** ***
 *  DESCRIPTION:
Â
 *   A PHP Class and MySQL table to find the distance between zip codes and
 *   find all zip codes within a given mileage or kilometer range.
 *   Â
 ************************** ********** ********** ********** ********** ********** ***
*/
// constants for setting the $units data member
define('_UNIT_MILES', 'm');
define('_UNIT_KILOMETERS', 'k');
// constants for passing $sort to get_zips_in_range()
define('_ZIPS_SORT_BY_DIST ANCE_ASC', 1);
define('_ZIPS_SORT_BY_DIST ANCE_DESC' , 2);
define('_ZIPS_SORT_BY_ZIP_ ASC', 3);
define('_ZIPS_SORT_BY_ZIP_ DESC', 4);
// constant for miles to kilometers conversion
define('_M2KM_FACTOR', 1.609344);
class zipcode_class {
  var $last_error = "";       // last error message set by this class
  var $last_time = 0;        // last function execution time (debug info)
  var $units = _UNIT_MILES;     // miles or kilometers
  var $decimals = 2;        // decimal places for returned distance
  function get_distance($zip1, $zip2) {
   // returns the distance between to zip codes.  If there is an error, the
   // function will return false and set the $last_error variable.
  Â
   $this->chronometer();     // start the clock
  Â
   if ($zip1 == $zip2) return 0; // same zip code means 0 miles between. :)
 Â
 Â
   // get details from database about each zip and exit if there is an error
  Â
   $details1 = $this->get_zip_point($zip1 );
   $details2 = $this->get_zip_point($zip2 );
   if ($details1 == false) {
     $this->last_error = "No details found for zip code: $zip1";
     return false;
   }
   if ($details2 == false) {
     $this->last_error = "No details found for zip code: $zip2";
     return false;
   }  Â
   // calculate the distance between the two points based on the lattitude
   // and longitude pulled out of the database.
  Â
   $miles = $this->calculate_mileage($ details1[0 ], $details2[0], $details1[1], $details2[1]);
  Â
   $this->last_time = $this->chronometer();
Â
   if ($this->units == _UNIT_KILOMETERS) return round($miles * _M2KM_FACTOR, $this->decimals);
   else return round($miles, $this->decimals);    // must be miles
  Â
  } Â
  function get_zip_details($zip) {
  Â
   // This function pulls the details from the database for a
   // given zip code.
Â
   $sql = "SELECT lat AS lattitude, lon AS longitude, city, county, state_prefix,
       state_name, area_code, time_zone
       FROM zip_code
       WHERE zip_code='$zip'";
      Â
   $r = mysql_query($sql);
   if (!$r) {
     $this->last_error = mysql_error();
     return false;
   } else {
     $row = mysql_fetch_array($r, MYSQL_ASSOC);
     mysql_free_result($r);
     return $row;   Â
   }
  }
  function get_zip_point($zip) {
 Â
   // This function pulls just the lattitude and longitude from the
   // database for a given zip code.
  Â
   $sql = "SELECT lat, lon from zip_code WHERE zip_code='$zip'";
   $r = mysql_query($sql);
   if (!$r) {
     $this->last_error = mysql_error();
     return false;
   } else {
     $row = mysql_fetch_array($r);
     mysql_free_result($r);
     return $row;   Â
   }   Â
  }
  function calculate_mileage($lat1, $lat2, $lon1, $lon2) {
Â
   // used internally, this function actually performs that calculation to
   // determine the mileage between 2 points defined by lattitude and
   // longitude coordinates.  This calculation is based on the code found
   // at http://www.cryptnet.net/fsp/zipdy/
   Â
   // Convert lattitude/longitude (degrees) to radians for calculations
   $lat1 = deg2rad($lat1);
   $lon1 = deg2rad($lon1);
   $lat2 = deg2rad($lat2);
   $lon2 = deg2rad($lon2);
  Â
   // Find the deltas
   $delta_lat = $lat2 - $lat1;
   $delta_lon = $lon2 - $lon1;
     Â
   // Find the Great Circle distance
   $temp = pow(sin($delta_lat/2.0),2) + cos($lat1) * cos($lat2) * pow(sin($delta_lon/2.0),2) ;
   $distance = 3956 * 2 * atan2(sqrt($temp),sqrt(1-$ temp));
   return $distance;
  }
 Â
  function get_zips_in_range($zip, $range, $sort=1, $include_base) {
   Â
   // returns an array of the zip codes within $range of $zip. Returns
   // an array with keys as zip codes and values as the distance from
   // the zipcode defined in $zip.
  Â
   $this->chronometer();           // start the clock
  Â
   $details = $this->get_zip_point($zip) ;  // base zip details
   if ($details == false) return false;
  Â
   // This portion of the routine  calculates the minimum and maximum lat and
   // long within a given range.  This portion of the code was written
   // by Jeff Bearer (http://www.jeffbearer.com). This significanly decreases
   // the time it takes to execute a query.  My demo took 3.2 seconds in
   // v1.0.0 and now executes in 0.4 seconds!  Greate job Jeff!
  Â
   // Find Max - Min Lat / Long for Radius and zero point and query
   // only zips in that range.
   $lat_range = $range/69.172;
   $lon_range = abs($range/(cos($details[0 ]) * 69.172));
   $min_lat = number_format($details[0] - $lat_range, "4", ".", "");
   $max_lat = number_format($details[0] + $lat_range, "4", ".", "");
   $min_lon = number_format($details[1] - $lon_range, "4", ".", "");
   $max_lon = number_format($details[1] + $lon_range, "4", ".", "");
   $return = array();   // declared here for scope
   $sql = "SELECT Zip, lat, lon FROM Suppliers2 ";
   if (!$include_base) $sql .= "WHERE Zip <> '$zip' AND ";
   else $sql .= "WHERE ";
   $sql .= "lat BETWEEN '$min_lat' AND '$max_lat'
        AND lon BETWEEN '$min_lon' AND '$max_lon'";
      Â
   $r = mysql_query($sql);
  Â
   if (!$r) {   // sql error
     $this->last_error = mysql_error();
     return false;
    Â
   } else {
    Â
     while ($row = mysql_fetch_row($r)) {
 Â
      // loop through all 40 some thousand zip codes and determine whether
      // or not it's within the specified range.
     Â
      $dist = $this->calculate_mileage($ details[0] ,$row[1],$ details[1] ,$row[2]);
      if ($this->units == _UNIT_KILOMETERS) $dist = $dist * _M2KM_FACTOR;
      if ($dist <= $range) {
        $return[str_pad($row[0], 5, "0", STR_PAD_LEFT)] = round($dist, $this->decimals);
      }
     }
     mysql_free_result($r);
   }
  Â
   // sort array
   switch($sort)
   {
     case _ZIPS_SORT_BY_DISTANCE_ASC :
      asort($return);
      break;
     Â
     case _ZIPS_SORT_BY_DISTANCE_DES C:
      arsort($return);
      break;
     Â
     case _ZIPS_SORT_BY_ZIP_ASC:
      ksort($return);
      break;
     Â
     case _ZIPS_SORT_BY_ZIP_DESC:
      krsort($return);
      break;
   }
  Â
   $this->last_time = $this->chronometer();
  Â
   if (empty($return)) return false;
   return $return;
  }
  function chronometer()  {
Â
  // chronometer function taken from the php manual.  This is used primarily
  // for debugging and anlyzing the functions while developing this class. Â
Â
  $now = microtime(TRUE);  // float, in _seconds_
  $now = $now + time();
  $malt = 1;
  $round = 7;
Â
  if ($this->last_time > 0) {
    /* Stop the chronometer : return the amount of time since it was started,
    in ms with a precision of 3 decimal places, and reset the start time.
    We could factor the multiplication by 1000 (which converts seconds
    into milliseconds) to save memory, but considering that floats can
    reach e+308 but only carry 14 decimals, this is certainly more precise */
  Â
    $retElapsed = round($now * $malt - $this->last_time * $malt, $round);
  Â
    $this->last_time = $now;
  Â
    return $retElapsed;
  } else {
    // Start the chronometer : save the starting time
 Â
    $this->last_time = $now;
  Â
    return 0;
  }
}
}
4. Home2.html
<form action="Results2.php" method="post">
 <div align="center" class="style10">
  <p>Please enter some key words of the products you look for (at least 4 characters)</p>
  <p><br />
   <input name="searchterm" type="text" size="60"/>
  </p>
  <p>Within
   <label>
   <select name="Radius" id="Radius">
    <option value="50">50</option>
    <option value="100" selected="selected">100</o ption>
    <option value="150">150</option>
    <option value="200">200</option>
    <option value="250">250</option>
    <option value="300">300</option>
   </select>
   </label>
miles from
<label>Destination Zip
<input name="Destination" type="text" id="Destination" maxlength="7" />
</label>
  </p>
  <p>     <br />
   <input type="submit" name="submit" value="Search"/>
   <input type="reset" name="Reset button" id="Reset button" value="Reset" />
  </p>
  <p> </p>
  <p>Register to get more detailed search results</p>
  <p><a href="Registration1.php">R egister</a > <span class="style9">|</span> <a href="Login1.php">Login</a ></p>
  <p> </p>
 </div>
</form>
5. Results2.php
<?php require_once('Connections/ sb0.php'); ?>
<?php require_once('zipcode.php' ); ?>
<?php
if (!function_exists("GetSQLV alueString ")) {
function GetSQLValueString($theValu e, $theType, $theDefinedValue = "", $theNotDefinedValue = "")
{
 $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;
 $theValue = function_exists("mysql_rea l_escape_s tring") ? mysql_real_escape_string($ theValue) : mysql_escape_string($theVa lue);
 switch ($theType) {
  case "text":
   $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
   break;  Â
  case "long":
  case "int":
   $theValue = ($theValue != "") ? intval($theValue) : "NULL";
   break;
  case "double":
   $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL";
   break;
  case "date":
   $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
   break;
  case "defined":
   $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
   break;
 }
 return $theValue;
}
}
$currentPage = $_SERVER["PHP_SELF"];
$maxRows_Recordset1 = 25;
$pageNum_Recordset1 = 0;
if (isset($_GET['pageNum_Reco rdset1'])) {
 $pageNum_Recordset1 = $_GET['pageNum_Recordset1' ];
}
$startRow_Recordset1 = $pageNum_Recordset1 * $maxRows_Recordset1;
$searchterm_Recordset1 = "4X4X4";
if (isset($_REQUEST['searchte rm'])) {
 $searchterm_Recordset1 = $_REQUEST['searchterm'];
}
mysql_select_db($database_ sb0, $sb0);
$query_Recordset1 = sprintf("SELECT * FROM Boxes, Suppliers2 WHERE MATCH (Description) AGAINST ( %s) AND Boxes.SID = Suppliers2.SID ORDER BY Suppliers2.Supplier_Name ASC", GetSQLValueString($searcht erm_Record set1, "text"));
$query_limit_Recordset1 = sprintf("%s LIMIT %d, %d", $query_Recordset1, $startRow_Recordset1, $maxRows_Recordset1);
$Recordset1 = mysql_query($query_limit_R ecordset1, $sb0) or die(mysql_error());
$row_Recordset1 = mysql_fetch_assoc($Records et1);
if (isset($_GET['totalRows_Re cordset1'] )) {
 $totalRows_Recordset1 = $_GET['totalRows_Recordset 1'];
} else {
 $all_Recordset1 = mysql_query($query_Records et1);
 $totalRows_Recordset1 = mysql_num_rows($all_Record set1);
}
$totalPages_Recordset1 = ceil($totalRows_Recordset1 /$maxRows_ Recordset1 )-1;
$queryString_Recordset1 = "";
if (!empty($_SERVER['QUERY_ST RING'])) {
 $params = explode("&", $_SERVER['QUERY_STRING']);
 $newParams = array();
 foreach ($params as $param) {
  if (stristr($param, "pageNum_Recordset1") == false &&Â
    stristr($param, "totalRows_Recordset1") == false) {
   array_push($newParams, $param);
  }
 }
 if (count($newParams) != 0) {
  $queryString_Recordset1 = "&" . htmlentities(implode("&", $newParams));
 }
}
$queryString_Recordset1 = sprintf("&totalRows_Record set1=%d%s& searchterm =%s",
 $totalRows_Recordset1, $queryString_Recordset1, urlencode($searchterm_Reco rdset1));
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
<!--
.style1 {color: #0033FF}
.style14 {font-family: "book Antiqua"; font-size: 24pt;}
.style15 {font-family: "segoe Print"; font-size: small;}
.style2 { Â Â Â Â Â color: #00FF00;
      font-family: "script MT Bold";
      font-size: larger;
}
.style5 {font-family: "book Antiqua"}
.style22 { Â Â Â Â Â color: #00FF00;
      font-family: "script MT Bold";
      font-size: 36px;
}
.style20 {font-family: "book Antiqua";
      font-size: 36pt;
      color: #0033FF;
}
.style21 {font-size: 24pt}
.style3 { Â Â Â Â Â font-family: "book Antiqua", "script MT Bold";
      font-size: 24pt;
      color: #0033FF;
}
-->
</style>
</head>
<body>
<form action="http://www.nnsourcebook.com/Results.php" method="post" name="form1" target="_blank" id="form2">
 <div align="left">
  <p><span class="style1"><span class="style3">N</span><sp an class="style20"><span class="style22"><sup>n </sup></span><span class="style21">SourceBook </span></s pan> <span class="style15">your sourcing assisstant</span></span></ p>
 </div>
 <label></label>
 <label></label>
 <div align="left"></div>
 <p align="right"><span class="style9"><a href="Home.html" title="Home" target="_blank">Home</a> | <a href="Company.html" title="Company" target="_blank">Company</a > | <a href="Categories.html" title="Category" target="_blank">Cateogries </a> | <a href="Contact.html" target="_blank">Contact</a ></span></ p>
</form>
<p>Records <?php echo ($startRow_Recordset1 + 1) ?> to <?php echo min($startRow_Recordset1 + $maxRows_Recordset1, $totalRows_Recordset1) ?> of <?php echo $totalRows_Recordset1 ?></p>
<table border="0">
 <tr>
  <td><?php if ($pageNum_Recordset1 > 0) { // Show if not first page ?>
     <a href="<?php printf("%s?pageNum_Records et1=%d%s", $currentPage, 0, $queryString_Recordset1); ?>">First</a>
     <?php } // Show if not first page ?>
  </td>
 <td><?php if ($pageNum_Recordset1 > 0) { // Show if not first page ?>
     <a href="<?php printf("%s?pageNum_Records et1=%d%s", $currentPage, max(0, $pageNum_Recordset1 - 1), $queryString_Recordset1); ?>">Previous</a>
     <?php } // Show if not first page ?>
  </td>
 <td><?php if ($pageNum_Recordset1 < $totalPages_Recordset1) { // Show if not last page ?>
     <a href="<?php printf("%s?pageNum_Records et1=%d%s", $currentPage, min($totalPages_Recordset1 , $pageNum_Recordset1 + 1), $queryString_Recordset1); ?>">Next</a>
     <?php } // Show if not last page ?>
  </td>
 <td><?php if ($pageNum_Recordset1 < $totalPages_Recordset1) { // Show if not last page ?>
     <a href="<?php printf("%s?pageNum_Records et1=%d%s", $currentPage, $totalPages_Recordset1, $queryString_Recordset1); ?>">Last</a>
     <?php } // Show if not last page ?>
  </td>
 </tr>
</table>
<table width="1000" border="1" align="left">
 <tr>
  <th width="50" scope="col"><div align="left">Supplier_Prod uct_Code</ div></th>
  <th scope="col">Description</t h>
  <th width="200" scope="col"><div align="center">Supplier_Na me</div></ th>
  <th width="50" scope="col"><div align="center">Zip</div></ th>
 Â
 </tr>
 <?php do { ?>
  <tr>
   <td width="50"><?php echo $row_Recordset1['Supplier_ Product_Co de']; ?></td>
   <td><?php echo $row_Recordset1['Descripti on']; ?></td>
   <td width="200"><div align="left"><?php echo $row_Recordset1['Supplier_ Name']; ?></div></td>
   <td width="50"><div align="left"><?php echo $row_Recordset1['Zip']; ?></div></td>
  Â
  </tr>
  <?php } while ($row_Recordset1 = mysql_fetch_assoc($Records et1)); ?>
</table>
</body>
</html>
<?php
mysql_free_result($Records et1);
?>
I copied from online free codes demo.php and zipcode.php and made a test page Radius.html. By trial, these three files seem work fine together. I can get a list of zip codes from my database that are within the range I specified in the Radius.html.
when it comes to integrate the scripts to my actual search page Home2.html and results page Results2.php, I am totally lost as a layman to PHP/MySql coding and newbie to Dreamweaver (I am using Dreamweaver CS3).
Any help would be highly appreciated. I have enclosed the srcipts of the five files I mentioned above.
1. Radius.html
<div id="mainContent">
  <form id="form2" name="form2" method="post" action="demo.php">
   Within a
   radius of
   <label>
   <select name="Radius" id="Radius">
    <option value="50">50</option>
    <option value="100" selected="selected">100</o
    <option value="150">150</option>
    <option value="200">200</option>
    <option value="250">250</option>
    <option value="300">300</option>
   </select>
   </label>
   miles from
   <label>Destination Zip
   <input name="Destination" type="text" id="Destination" maxlength="7" />
   </label>
   <p>
2. demo.php
<?php
/* Â
  DEMO for using the zipcode PHP class. By: Micah Carrick
  Questions?  Comments?  Suggestions?  email@micahcarrick.com
*/
require_once('zipcode.php'
// Open up a connection to the database. Â The sql required to create the MySQL
// tables and populate them with the data is in the /sql subfolder. Â You can
// upload those sql files using phpMyAdmin or a MySQL prompt. Â You will have to
// modify the below information to your database information. Â
mysql_connect('localhost',
mysql_select_db('db') or die(mysql_error());
// Below is an example of how to calculate the distance between two zip codes.
$Radius = $_POST['Radius'];
$Destination = $_POST['Destination'];
echo '<h3>zip codes withing the radius of your destination</h3>';
$z = new zipcode_class;
$zips = $z->get_zips_in_range($Des
if ($zips === false) echo 'Error: '.$z->last_error;
else {
 Â
  foreach ($zips as $key => $value) {
   echo "Zip code <b>$key</b> is <b>$value</b> miles away from <b>'$Destination'</b>.<br />";
  }
 Â
  // One thing you may want to do with this is create SQL from it. For example,
  // iterate through the array to create SQL that is something like:
  // WHERE zip_code IN ('93001 93002 93004')
  // and then use that condition in your query to find all pizza joints or
  // whatever you're using it for. Make sense? Hope so.
 Â
  echo "<br /><i>get_zips_in_range() executed in <b>".$z->last_time."</b> seconds.</i><br />";
}
// And one more example of using the class to simply get the information about
// a zip code. Â You can then do whatever you want with it. Â The array returned
// from the function has the database field names as the keys. Â I just do a
// couple string converstions to make them more readable.
echo '<h3>details about your destination</h3>';
$Destination = $_POST['Destination'];
$details = $z->get_zip_details($Desti
if ($details === false) echo 'Error: '.$z->last_error;
else {
  foreach ($details as $key => $value) {
   $key = str_replace('_',' ',$key);
   $key = ucwords($key);
   echo "$key: $value<br />";
  }
}
?>
3. zipcode.php
<?php
/*************************
 *         ZIP Code and Distance Claculation Class
 **************************
 *    Author:   Micah Carrick
 *    Email:    email@micahcarrick.com
 *    Website:   http://www.micahcarrick.com
 *
 *    File:    zipcode.class.php
 *    Version:   1.2.0
 *    Copyright:  (c) 2005 - Micah Carrick
 *          You are free to use, distribute, and modify this software
 *          under the terms of the GNU General Public License.  See the
 *          included license.txt file.
 *
 **************************
 *  VERION HISTORY:
 *    v1.2.0 [Oct 22, 2006] - Using a completely new database based on user
                contributions which resolves many data bugs.
               - Added sorting to get_zips_in_range()
               - Added ability to include/exclude the base zip
                from get_zips_in_range()
              Â
 *    v1.1.0 [Apr 30, 2005] - Added Jeff Bearer's code to make it MUCH faster!
Â
 *    v1.0.1 [Apr 22, 2005] - Fixed a typo :)
Â
 *    v1.0.0 [Apr 12, 2005] - Initial Version
 *
 **************************
 *  DESCRIPTION:
Â
 *   A PHP Class and MySQL table to find the distance between zip codes and
 *   find all zip codes within a given mileage or kilometer range.
 *   Â
 **************************
*/
// constants for setting the $units data member
define('_UNIT_MILES', 'm');
define('_UNIT_KILOMETERS',
// constants for passing $sort to get_zips_in_range()
define('_ZIPS_SORT_BY_DIST
define('_ZIPS_SORT_BY_DIST
define('_ZIPS_SORT_BY_ZIP_
define('_ZIPS_SORT_BY_ZIP_
// constant for miles to kilometers conversion
define('_M2KM_FACTOR', 1.609344);
class zipcode_class {
  var $last_error = "";       // last error message set by this class
  var $last_time = 0;        // last function execution time (debug info)
  var $units = _UNIT_MILES;     // miles or kilometers
  var $decimals = 2;        // decimal places for returned distance
  function get_distance($zip1, $zip2) {
   // returns the distance between to zip codes.  If there is an error, the
   // function will return false and set the $last_error variable.
  Â
   $this->chronometer();     // start the clock
  Â
   if ($zip1 == $zip2) return 0; // same zip code means 0 miles between. :)
 Â
 Â
   // get details from database about each zip and exit if there is an error
  Â
   $details1 = $this->get_zip_point($zip1
   $details2 = $this->get_zip_point($zip2
   if ($details1 == false) {
     $this->last_error = "No details found for zip code: $zip1";
     return false;
   }
   if ($details2 == false) {
     $this->last_error = "No details found for zip code: $zip2";
     return false;
   }  Â
   // calculate the distance between the two points based on the lattitude
   // and longitude pulled out of the database.
  Â
   $miles = $this->calculate_mileage($
  Â
   $this->last_time = $this->chronometer();
Â
   if ($this->units == _UNIT_KILOMETERS) return round($miles * _M2KM_FACTOR, $this->decimals);
   else return round($miles, $this->decimals);    // must be miles
  Â
  } Â
  function get_zip_details($zip) {
  Â
   // This function pulls the details from the database for a
   // given zip code.
Â
   $sql = "SELECT lat AS lattitude, lon AS longitude, city, county, state_prefix,
       state_name, area_code, time_zone
       FROM zip_code
       WHERE zip_code='$zip'";
      Â
   $r = mysql_query($sql);
   if (!$r) {
     $this->last_error = mysql_error();
     return false;
   } else {
     $row = mysql_fetch_array($r, MYSQL_ASSOC);
     mysql_free_result($r);
     return $row;   Â
   }
  }
  function get_zip_point($zip) {
 Â
   // This function pulls just the lattitude and longitude from the
   // database for a given zip code.
  Â
   $sql = "SELECT lat, lon from zip_code WHERE zip_code='$zip'";
   $r = mysql_query($sql);
   if (!$r) {
     $this->last_error = mysql_error();
     return false;
   } else {
     $row = mysql_fetch_array($r);
     mysql_free_result($r);
     return $row;   Â
   }   Â
  }
  function calculate_mileage($lat1, $lat2, $lon1, $lon2) {
Â
   // used internally, this function actually performs that calculation to
   // determine the mileage between 2 points defined by lattitude and
   // longitude coordinates.  This calculation is based on the code found
   // at http://www.cryptnet.net/fsp/zipdy/
   Â
   // Convert lattitude/longitude (degrees) to radians for calculations
   $lat1 = deg2rad($lat1);
   $lon1 = deg2rad($lon1);
   $lat2 = deg2rad($lat2);
   $lon2 = deg2rad($lon2);
  Â
   // Find the deltas
   $delta_lat = $lat2 - $lat1;
   $delta_lon = $lon2 - $lon1;
     Â
   // Find the Great Circle distance
   $temp = pow(sin($delta_lat/2.0),2)
   $distance = 3956 * 2 * atan2(sqrt($temp),sqrt(1-$
   return $distance;
  }
 Â
  function get_zips_in_range($zip, $range, $sort=1, $include_base) {
   Â
   // returns an array of the zip codes within $range of $zip. Returns
   // an array with keys as zip codes and values as the distance from
   // the zipcode defined in $zip.
  Â
   $this->chronometer();           // start the clock
  Â
   $details = $this->get_zip_point($zip)
   if ($details == false) return false;
  Â
   // This portion of the routine  calculates the minimum and maximum lat and
   // long within a given range.  This portion of the code was written
   // by Jeff Bearer (http://www.jeffbearer.com). This significanly decreases
   // the time it takes to execute a query.  My demo took 3.2 seconds in
   // v1.0.0 and now executes in 0.4 seconds!  Greate job Jeff!
  Â
   // Find Max - Min Lat / Long for Radius and zero point and query
   // only zips in that range.
   $lat_range = $range/69.172;
   $lon_range = abs($range/(cos($details[0
   $min_lat = number_format($details[0] - $lat_range, "4", ".", "");
   $max_lat = number_format($details[0] + $lat_range, "4", ".", "");
   $min_lon = number_format($details[1] - $lon_range, "4", ".", "");
   $max_lon = number_format($details[1] + $lon_range, "4", ".", "");
   $return = array();   // declared here for scope
   $sql = "SELECT Zip, lat, lon FROM Suppliers2 ";
   if (!$include_base) $sql .= "WHERE Zip <> '$zip' AND ";
   else $sql .= "WHERE ";
   $sql .= "lat BETWEEN '$min_lat' AND '$max_lat'
        AND lon BETWEEN '$min_lon' AND '$max_lon'";
      Â
   $r = mysql_query($sql);
  Â
   if (!$r) {   // sql error
     $this->last_error = mysql_error();
     return false;
    Â
   } else {
    Â
     while ($row = mysql_fetch_row($r)) {
 Â
      // loop through all 40 some thousand zip codes and determine whether
      // or not it's within the specified range.
     Â
      $dist = $this->calculate_mileage($
      if ($this->units == _UNIT_KILOMETERS) $dist = $dist * _M2KM_FACTOR;
      if ($dist <= $range) {
        $return[str_pad($row[0], 5, "0", STR_PAD_LEFT)] = round($dist, $this->decimals);
      }
     }
     mysql_free_result($r);
   }
  Â
   // sort array
   switch($sort)
   {
     case _ZIPS_SORT_BY_DISTANCE_ASC
      asort($return);
      break;
     Â
     case _ZIPS_SORT_BY_DISTANCE_DES
      arsort($return);
      break;
     Â
     case _ZIPS_SORT_BY_ZIP_ASC:
      ksort($return);
      break;
     Â
     case _ZIPS_SORT_BY_ZIP_DESC:
      krsort($return);
      break;
   }
  Â
   $this->last_time = $this->chronometer();
  Â
   if (empty($return)) return false;
   return $return;
  }
  function chronometer()  {
Â
  // chronometer function taken from the php manual.  This is used primarily
  // for debugging and anlyzing the functions while developing this class. Â
Â
  $now = microtime(TRUE);  // float, in _seconds_
  $now = $now + time();
  $malt = 1;
  $round = 7;
Â
  if ($this->last_time > 0) {
    /* Stop the chronometer : return the amount of time since it was started,
    in ms with a precision of 3 decimal places, and reset the start time.
    We could factor the multiplication by 1000 (which converts seconds
    into milliseconds) to save memory, but considering that floats can
    reach e+308 but only carry 14 decimals, this is certainly more precise */
  Â
    $retElapsed = round($now * $malt - $this->last_time * $malt, $round);
  Â
    $this->last_time = $now;
  Â
    return $retElapsed;
  } else {
    // Start the chronometer : save the starting time
 Â
    $this->last_time = $now;
  Â
    return 0;
  }
}
}
4. Home2.html
<form action="Results2.php" method="post">
 <div align="center" class="style10">
  <p>Please enter some key words of the products you look for (at least 4 characters)</p>
  <p><br />
   <input name="searchterm" type="text" size="60"/>
  </p>
  <p>Within
   <label>
   <select name="Radius" id="Radius">
    <option value="50">50</option>
    <option value="100" selected="selected">100</o
    <option value="150">150</option>
    <option value="200">200</option>
    <option value="250">250</option>
    <option value="300">300</option>
   </select>
   </label>
miles from
<label>Destination Zip
<input name="Destination" type="text" id="Destination" maxlength="7" />
</label>
  </p>
  <p>     <br />
   <input type="submit" name="submit" value="Search"/>
   <input type="reset" name="Reset button" id="Reset button" value="Reset" />
  </p>
  <p> </p>
  <p>Register to get more detailed search results</p>
  <p><a href="Registration1.php">R
  <p> </p>
 </div>
</form>
5. Results2.php
<?php require_once('Connections/
<?php require_once('zipcode.php'
<?php
if (!function_exists("GetSQLV
function GetSQLValueString($theValu
{
 $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;
 $theValue = function_exists("mysql_rea
 switch ($theType) {
  case "text":
   $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
   break;  Â
  case "long":
  case "int":
   $theValue = ($theValue != "") ? intval($theValue) : "NULL";
   break;
  case "double":
   $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL";
   break;
  case "date":
   $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
   break;
  case "defined":
   $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
   break;
 }
 return $theValue;
}
}
$currentPage = $_SERVER["PHP_SELF"];
$maxRows_Recordset1 = 25;
$pageNum_Recordset1 = 0;
if (isset($_GET['pageNum_Reco
 $pageNum_Recordset1 = $_GET['pageNum_Recordset1'
}
$startRow_Recordset1 = $pageNum_Recordset1 * $maxRows_Recordset1;
$searchterm_Recordset1 = "4X4X4";
if (isset($_REQUEST['searchte
 $searchterm_Recordset1 = $_REQUEST['searchterm'];
}
mysql_select_db($database_
$query_Recordset1 = sprintf("SELECT * FROM Boxes, Suppliers2 WHERE MATCH (Description) AGAINST ( %s) AND Boxes.SID = Suppliers2.SID ORDER BY Suppliers2.Supplier_Name ASC", GetSQLValueString($searcht
$query_limit_Recordset1 = sprintf("%s LIMIT %d, %d", $query_Recordset1, $startRow_Recordset1, $maxRows_Recordset1);
$Recordset1 = mysql_query($query_limit_R
$row_Recordset1 = mysql_fetch_assoc($Records
if (isset($_GET['totalRows_Re
 $totalRows_Recordset1 = $_GET['totalRows_Recordset
} else {
 $all_Recordset1 = mysql_query($query_Records
 $totalRows_Recordset1 = mysql_num_rows($all_Record
}
$totalPages_Recordset1 = ceil($totalRows_Recordset1
$queryString_Recordset1 = "";
if (!empty($_SERVER['QUERY_ST
 $params = explode("&", $_SERVER['QUERY_STRING']);
 $newParams = array();
 foreach ($params as $param) {
  if (stristr($param, "pageNum_Recordset1") == false &&Â
    stristr($param, "totalRows_Recordset1") == false) {
   array_push($newParams, $param);
  }
 }
 if (count($newParams) != 0) {
  $queryString_Recordset1 = "&" . htmlentities(implode("&", $newParams));
 }
}
$queryString_Recordset1 = sprintf("&totalRows_Record
 $totalRows_Recordset1, $queryString_Recordset1, urlencode($searchterm_Reco
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
<!--
.style1 {color: #0033FF}
.style14 {font-family: "book Antiqua"; font-size: 24pt;}
.style15 {font-family: "segoe Print"; font-size: small;}
.style2 { Â Â Â Â Â color: #00FF00;
      font-family: "script MT Bold";
      font-size: larger;
}
.style5 {font-family: "book Antiqua"}
.style22 { Â Â Â Â Â color: #00FF00;
      font-family: "script MT Bold";
      font-size: 36px;
}
.style20 {font-family: "book Antiqua";
      font-size: 36pt;
      color: #0033FF;
}
.style21 {font-size: 24pt}
.style3 { Â Â Â Â Â font-family: "book Antiqua", "script MT Bold";
      font-size: 24pt;
      color: #0033FF;
}
-->
</style>
</head>
<body>
<form action="http://www.nnsourcebook.com/Results.php" method="post" name="form1" target="_blank" id="form2">
 <div align="left">
  <p><span class="style1"><span class="style3">N</span><sp
 </div>
 <label></label>
 <label></label>
 <div align="left"></div>
 <p align="right"><span class="style9"><a href="Home.html" title="Home" target="_blank">Home</a> | <a href="Company.html" title="Company" target="_blank">Company</a
</form>
<p>Records <?php echo ($startRow_Recordset1 + 1) ?> to <?php echo min($startRow_Recordset1 + $maxRows_Recordset1, $totalRows_Recordset1) ?> of <?php echo $totalRows_Recordset1 ?></p>
<table border="0">
 <tr>
  <td><?php if ($pageNum_Recordset1 > 0) { // Show if not first page ?>
     <a href="<?php printf("%s?pageNum_Records
     <?php } // Show if not first page ?>
  </td>
 <td><?php if ($pageNum_Recordset1 > 0) { // Show if not first page ?>
     <a href="<?php printf("%s?pageNum_Records
     <?php } // Show if not first page ?>
  </td>
 <td><?php if ($pageNum_Recordset1 < $totalPages_Recordset1) { // Show if not last page ?>
     <a href="<?php printf("%s?pageNum_Records
     <?php } // Show if not last page ?>
  </td>
 <td><?php if ($pageNum_Recordset1 < $totalPages_Recordset1) { // Show if not last page ?>
     <a href="<?php printf("%s?pageNum_Records
     <?php } // Show if not last page ?>
  </td>
 </tr>
</table>
<table width="1000" border="1" align="left">
 <tr>
  <th width="50" scope="col"><div align="left">Supplier_Prod
  <th scope="col">Description</t
  <th width="200" scope="col"><div align="center">Supplier_Na
  <th width="50" scope="col"><div align="center">Zip</div></
 Â
 </tr>
 <?php do { ?>
  <tr>
   <td width="50"><?php echo $row_Recordset1['Supplier_
   <td><?php echo $row_Recordset1['Descripti
   <td width="200"><div align="left"><?php echo $row_Recordset1['Supplier_
   <td width="50"><div align="left"><?php echo $row_Recordset1['Zip']; ?></div></td>
  Â
  </tr>
  <?php } while ($row_Recordset1 = mysql_fetch_assoc($Records
</table>
</body>
</html>
<?php
mysql_free_result($Records
?>
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
DomerBill, I have the exact same issue with integrating the zip code radius search php code into my site and I am using Dreamweaver as well. Can you provide a link to description of the forum where you found your answer?
ASKER