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