Link to home
Start Free TrialLog in
Avatar of DomerBill
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</option>
        <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','pwd') 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($Destination, $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($Destination);

if ($details === false) echo 'Error: '.$z->last_error;
else {
   foreach ($details as $key => $value) {
      $key = str_replace('_',' ',$key);
      $key = ucwords($key);
      echo "$key:&nbsp;$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_DISTANCE_ASC', 1);
define('_ZIPS_SORT_BY_DISTANCE_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_DESC:
            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</option>
        <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>&nbsp;</p>
    <p>Register to get more detailed search results</p>
    <p><a href="Registration1.php">Register</a> <span class="style9">|</span> <a href="Login1.php">Login</a></p>
    <p>&nbsp;</p>
  </div>
</form>

5. Results2.php
<?php require_once('Connections/sb0.php'); ?>
<?php require_once('zipcode.php'); ?>
<?php
if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "")
{
  $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;

  $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

  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_Recordset1'])) {
  $pageNum_Recordset1 = $_GET['pageNum_Recordset1'];
}
$startRow_Recordset1 = $pageNum_Recordset1 * $maxRows_Recordset1;

$searchterm_Recordset1 = "4X4X4";
if (isset($_REQUEST['searchterm'])) {
  $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($searchterm_Recordset1, "text"));
$query_limit_Recordset1 = sprintf("%s LIMIT %d, %d", $query_Recordset1, $startRow_Recordset1, $maxRows_Recordset1);
$Recordset1 = mysql_query($query_limit_Recordset1, $sb0) or die(mysql_error());
$row_Recordset1 = mysql_fetch_assoc($Recordset1);

if (isset($_GET['totalRows_Recordset1'])) {
  $totalRows_Recordset1 = $_GET['totalRows_Recordset1'];
} else {
  $all_Recordset1 = mysql_query($query_Recordset1);
  $totalRows_Recordset1 = mysql_num_rows($all_Recordset1);
}
$totalPages_Recordset1 = ceil($totalRows_Recordset1/$maxRows_Recordset1)-1;

$queryString_Recordset1 = "";
if (!empty($_SERVER['QUERY_STRING'])) {
  $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_Recordset1=%d%s&searchterm=%s",
  $totalRows_Recordset1, $queryString_Recordset1, urlencode($searchterm_Recordset1));

?>
<!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><span class="style20"><span class="style22"><sup>n </sup></span><span class="style21">SourceBook</span></span> <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_Recordset1=%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_Recordset1=%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_Recordset1=%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_Recordset1=%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_Product_Code</div></th>
    <th scope="col">Description</th>
    <th width="200" scope="col"><div align="center">Supplier_Name</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_Code']; ?></td>
      <td><?php echo $row_Recordset1['Description']; ?></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($Recordset1)); ?>
</table>


</body>
</html>
<?php
mysql_free_result($Recordset1);
?>
ASKER CERTIFIED SOLUTION
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of DomerBill
DomerBill

ASKER

Thanks for your response and advice. I was able to solve it by refering to another forum this morning.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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?