Search By Location (Miles From Zip Code) in PHP

Whenever you’re building a site that has a directory of businesses or people or anything with a physical location, it commonly lends itself to offering a search form which allows the user to search by distance from a given location.

For example, a national or state-wide company with many branches may want to allow their website visitors to find a location near them. Or perhaps you may be building a directory of specialist doctors, or a site with real estate listings, and want to offer users the ability to search within X miles from a given location. It sounds like a difficult feature to implement but in reality it is not.

The solution comes in essentially three parts, a zip code database, your database of items/people/businesses, and a small PHP script. The database is list of city, state, and county information that is linked to latitude and longitude information, which allows the script to determine where zip codes are in relationship to one another. A flexible class is provided to allow simple access to the zip code functions.

This article does assume that you have a basic understanding of working with PHP and MySQL. Make sure to download the zip archive containing the database and associated scripts before getting started.

Part 1: Setting Up The Zip Code Database

You’ll find 6 SQL files in the /sql directory of the zip file that you must also run in order to load the zip code database into MySQL. Make sure to run create_table.sql first in order to create the zip code database table before loading in its entries, which have been split up into data_1.sql, data_2.sql and so on. The zip code database contains over 40,000 rows so it has been split up into 5 parts to allow importing from a web browser via phpMyAdmin’s “Import” tab.

Part 2: Setting Up Your Database

Additionally, we will need a database of things to search for, so we’ll use a database of properties that might be for sale as an example. Below is some very basic SQL for our properties table:

CREATE TABLE `properties` (
`id` int(11) unsigned NOT NULL auto_increment,
`zip_code` varchar(5) collate utf8_bin NOT NULL,
`address` varchar(50) collate utf8_bin default NULL,
`seller_name` varchar(50) collate utf8_bin default NULL,
PRIMARY KEY  (`id`),
KEY `zip_code` (`zip_code`)
)

The key field in the table above is zip_code, as you can imagine, the other fields could really be anything that might be associated with a zip code. After creating our table, add some records to it.

Part 3: The Search Form

For the purposes of this post we’ll use a simple zipcode field to search, as reviewing the details of creating a teired city, state, zip selection fieldset warrants a post of its own. So we might have a search field on our search.htm page that looks like this:

<!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>Zip Code Search</title>
</head>

<body>
<form method="post" action="results.php">
<label for="miles">Search within </label>
<input type="text" name="miles" id="miles" size="10" />
miles of
<label for="zip_code"></label>
<input type="text" name="zip_code" id="zip_code"  />
<input type="submit" name="submit" value="Search" />
</form>
</body>
</html>

Part 4: The Search Results Page

Now that we have both of our database tables setup, and our search form, we must create the results.php script to process our form submission and generate a result (find the items within X miles of a given zip code!) The full source code is below:

require_once('zipcode.class.php');
mysql_connect('host','username','password') or die(mysql_error());
mysql_select_db('database_name') or die(mysql_error());

$z = new zipcode_class;
$zips = $z->get_zips_in_range($_POST['zip_code'], $_POST['miles'], _ZIPS_SORT_BY_DISTANCE_ASC, true);

if ($zips === false) {
echo 'Error: '.$z->last_error;
} else {
$zips_in_range = implode(',', array_keys($zips) );
}

$result = mysql_query("SELECT * FROM properties WHERE zip_code IN (". $zips_in_range . ")");
while ($row = mysql_fetch_assoc($result) ) {
print_r($row);
}

Let’s go through the above script line by line and review what is happening.

  1. We include the zipcode class, which contains all of the goodies for calculating distances and whatnot.
  2. Connect to our mysql database, make sure to fill in your own info on this line.
  3. Tell the script which database to use, make sure to fill in your own info.
  4. Inhale…
  5. Instantiate the zipcode class and assign it to the $z variable.
  6. Call the get_zips_in_range function and pass it the zip and miles variables in the POST array, ask for results sorted by distance, shortest to furthest, and ask it to include the zipcode you searched for in the results
  7. Inhale…
  8. Make sure there were no errors encountered while searching the zip code database.
  9. Print any errors that may have occurred
  10. But if things went well…
  11. Take all of the zip codes within range using array_keys($zips) and turn them in a comma seperated list with implode() and assign it to $zips_in_range
  12. Select all records from the properties table which we created above that have a zip code IN the list of zip codes returned from the function on line 6.
  13. Traverse the result set and print each row to see what properties have been returned!
  14. Tada!

Some Final Words

Obviously this is a bare bones example but I hope that I have illustrated one way of using a great script to accomplish a very useful task on your websites; I am sure it will come in handy time and time again. There are obviously some poor programming practices being illustrated above for the sake of brevity, such as using raw POST data in a function without sanitizing it first, and I hope you will take these things into consideration as you build out your website. The zipcode class that was used in this example was created by Micah Carrick, and actually contains a whole host of other nice features such as calculating the distance between two coordinates, calculating the distance between two zip codes, and returning information about a given zip code. I’ve included my additional search.htm and results.php files, which are detailed above for you to experiment with in addition to the provided demo.php originally included in the archive. If you have any questions about specific implementations or modifying the techniques covered above, please comment below.

Download zipcode-1.2.0.zip [1MB]

  • Willie
    Hello there:

    Thanks a lot for this post clarifying how to use the code by Micah. It is greatly appreciated.

    I am using your code to get Micah's class to work for me. However, I am getting an error in this line:

    $zips_in_range = implode(',', array_keys($zips) );

    The error is:

    Warning: array_keys() [function.array-keys]: The first argument should be an array in /opt/www/vhosts/company/www/zipclass.index.php on line 14

    I hope you, or someone else, can help me to solve this
    I dont know if this enough info to solve this error.

    Thanks.
    --Willie
  • Willie
    Hello There:

    Please ignore my previous post. I found what the problem was. I was inputting the inputs backwards. Thanks.
    --Willie
  • sophistihip
    Willie,

    I'm glad you've figured it out, good luck!
blog comments powered by Disqus