Get the Lat/Lon Location of Major US Cities
Published: January 27th, 2009 by: Andrew
In this article, learn how to fetch the latitude & longitude location of all major US cities. I'm going to provide you with a comprehensive list of almost 500 major US cities as well as the source, so you can get the updated list as city sizes change.
This data is provided by the National Digital Forecast Database (NDFD). They supply the city data in groups, or all at once, so you won’t be making calls to this service often, as city locations don’t normally change. As a result, you can skip the task of writing XML parsing and import scripts, and just import the data directly from here. I have prepared a SQL import file straight from this data with no alterations.
This data is retrieved by calling the LatLonListCityNames() function from the NDFD. The National Weather Service presents the cities in 4 different levels. More information can be found by viewing their NDFD page and scroll down to the the section that describes the LatLonListCityNames() function.
Example: Query the Database for a City Name
The following code is the best way to find the closest city for the lat/lon provided.
<?php /** * This is how I connect to my database - adjust as necessary */ include('../includes/database.php'); $db_link = db_connect(); function get_city_names($lat, $lon, $count = 1) { global $db_link; $lat = (float)$lat; $lon = (float)$lon; /** * this query does all the work - with a little math, * we can search by cloest results */ $query = "SELECT *, SQRT(POW(69.1 * (lat - $lat), 2) + POW(69.1 * ($lon - lon) * COS(lat / 57.3 ), 2 )) AS distance FROM CityNames ORDER BY distance ASC LIMIT $count"; $result = mysql_query($query, $db_link); /** * no need for a multi-dimensial array if there is * only one result */ if (mysql_num_rows($result) == 1) { return mysql_fetch_assoc($result); } else { $rows = array(); for ($i = 0, $c = mysql_num_rows($result); $i < $c; $i++) { $rows[] = mysql_fetch_assoc($result); } } return $rows; } /** * Get the 5 closest cities to the given coordinates */ $cities = get_city_names(41.9224, -87.6524, 5); header('Content-type: text/plain'); var_dump($cities); /** * Why do I comment out my PHP closing tag? It's actually not needed! * See: http://phpstarter.net/2009/01/omit-the-php-closing-tag/ */ /* ?> */
Example: Fetching the City Names from the NDFD
You do not need to know this if you use the SQL import file offered above. If you want to know how this data was retrieved, here is an example. It requires a copy of NuSOAP, so download yourself a copy if you don’t have it.
<?php /** * Download NuSOAP from the link below and change the require path accordingly * http://sourceforge.net/projects/nusoap/ */ require('../includes/nusoap/nusoap.php'); /** * Fetch the list of cities & location from the NDFD * * @param int $level the city level to import (http://www.weather.gov/xml/) * @return mixed */ function import_city_names($level = 1) { $level = (int)$level; /** * SOAP parameters go here. We only need to send the city level */ $parameters = array('displayLevel' => $level); /** * couple things can go wrong here; the soap request can fail, or we can * be sent an invalid XML file, which would cause problems */ try { $c = new nusoap_client('http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl', 'wsdl'); $result = $c->call('LatLonListCityNames', $parameters, '', '', false, true); $xml = new SimpleXMLElement($c->return['listLatLonOut']); } catch (Exception $e) { /* fail! */ return false; } /** * parse through the XML fields * run var_dump($xml) to see how the XML data fields are formed */ $city_name_list = explode('|', $xml->cityNameList); $lat_lon_list = explode(' ', $xml->latLonList); $data = array(); for ($i = 0, $c = count($city_name_list); $i < $c; $i++) { $row = array(); list($row['city'], $row['state']) = explode(',', array_pop($city_name_list)); list($row['lat'], $row['lon']) = explode(',', array_pop($lat_lon_list)); $data[] = $row; } return $data; } /* run the function to list all level 1 cities */ $cities = import_city_names(1); /** * For demonstration purposes, we are just going to dump the data. * If this were a production script, we would be putting it in storage (database, etc) */ var_dump($cities); /** * Why do I comment out my PHP closing tag? It's actually not needed! * See: http://phpstarter.net/2009/01/omit-the-php-closing-tag/ */ /* ?> */
Do not use this function every time you need to lookup a city. This information is rarely updated, so it’s best to load it into a database or flat file for storage and retrieval as necessary.
I used this source to search for a weather forecast by city. This data isn’t perfect as it doesn’t cover every town and village, but it covers enough for my purposes. If you know of a free data source that gets more specific, please share in a comment.