arguments.callee web design & development blog  


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);
    }
?>
Tags




blog comments powered by Disqus
search blog
categories & tags
random posts
about hb stone

I'm a Senior Culinary Software Developer at Yummly working on various front-end and middle-tier tasks, primarily using JavaScript. I blog about web design and development topics including accessibility, usability, performance, and developing HTML / CSS / JavaScript applications on Appcelerator Titanium and Adobe AIR.

If you're a web developer, you might enjoy Jelo, my JavaScript library.

copyright

All original work on this site is covered by a Creative Commons Attribution 3.0 license unless otherwise specified.

You may share or use any code or images from this site in any manner, for free, so long as reasonable effort has been made to give credit where due.

The views expressed in the posts and comments on this blog do not necessarily reflect those of my current or former employers.