start blog post

Convert ZIP code to a Yahoo! WOEID

If you want to get the current weather (or weather forecast) for a given location, you might be tempted to find that information by ZIP code. Until this week, you would be able to use Yahoo's Weather RSS feed. A URL like http://weather.yahooapis.com/forecastrss?p=92260 would return weather information for the ZIP code 92260. Easy!

If you've already done that, you may have noticed your service no longer works. This is because Yahoo! recently switched to only allow "Where On Earth" IDs (WOEIDs) as input for their weather API. The reasoning behind this is better integration with Yahoo's family of geo technologies like Placemaker, GeoPlanet, GeoPlanet Data, Fire Eagle, and Yahoo! Maps.

But don't fret, it's easy to convert your ZIP code to a Yahoo! WOEID.

<?php
    function getWOEID($zip) {
        // use YQL to find the WOEID
        $q = "select woeid from geo.places where text='$zip' limit 1";
        
        // execute the YQL query we just built
        $ch = curl_init('http://query.yahooapis.com/v1/public/YQL?format=json&q=' . urlencode($q));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        
        // if we got something back
        if ($response) {
      try {
              $response = json_decode($response, true);               // convert JSON to an array
              return $response['query']['results']['place']['woeid']; // path to the WOEID value
      } catch(Exception $ex) {
        return 0; // invalid response, we may have hit the rate limit (see next section)
      }
        }
        
        return 0; // we received no response at all
    }
    
    // change "?p=" to "?w=" in your URL, that's it!
    $url = "http://weather.yahooapis.com/forecastrss?w=" . getWOEID($_GET['zip']);
    
    // fetch Yahoo's weather RSS feed
    $ch = curl_init($url);
    curl_exec($ch);
    curl_close($ch);
?>

Show Me the Cache

One important thing to note is that WOEIDs will not change, at least not in the forseeable future. Once you convert one zip code, there's no reason to ever call that same query again. To avoid possibly hitting the YQL public API rate limit we can cache the responses we get back. You can do so in a database, but here's a quick and easy file-based cache which works just as well:

<?php
    function getWOEID($loc) {

        $cache = "./cache/$loc.txt";
        // if the cache directory doesn't already exist, make it
        if (!is_dir('cache')) {
            mkdir('cache');
        }
        if (file_exists($cache)) {
            return file_get_contents($cache);
        }
    
    // same query as in the first example
        $q = "select woeid from geo.places where text='$loc' limit 1";
        $ch = curl_init('http://query.yahooapis.com/v1/public/yql?format=json&q=' . urlencode($q));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        if ($response) {
            try {
                $response = json_decode($response, true);
                $response = intval($response['query']['results']['place']['woeid']);
        
        // this block is new, we store the response locally
                if (intval($response)) { // only cache valid responses
                    file_put_contents($cache, $response);
                    return $response;
                }
        
            } catch(Exception $ex) {
                return intval(0);
            }
        }
        return intval(0);
    }
?>

var tags = [];

  • share this post:
  • email a friend
  • float this post
  • digg this post
  • share on stumbleupon
  • submit to technorati
  • tweet this post

end blog post

most viewed this week

least viewed this week