Google Weather API Class

Most updated code is now on Github.

https://github.com/redinkdesign/Google-Weather-API

    • Ashwin Surajbali
    • April 14th, 2009

    New revision added. Google’s ICON url changed and the code has been updated.

    • Erin
    • May 19th, 2009

    Thank you so much for sharing this script. Its awesome.

    • Ashwin Surajbali
    • May 20th, 2009

    Code updated again at line 123.

    Changed from

    $return_array['forecast'][$i]['icon'] = ‘http://img0.gmodules.com/ig/’ . $data->icon['data'];

    to

    $return_array['forecast'][$i]['icon'] = ‘http://img0.gmodules.com/’ . $data->icon['data'];

    Stop changing image paths google :)

    • Johnathan
    • June 23rd, 2009

    I’m looking to include a similar class in a personal project I’m working on (GNU License). What’s your license on this PHP Class?

    • Ashwin Surajbali
    • June 24th, 2009

    Hey, it would be GNU as well. I will update the post…thanks.

    • Johnathan
    • June 29th, 2009

    Great! I’ll drop you a line if/when my project gets completed.

    Thanks for your work on this. It’ll save me a good chunk of time.

    • César Couto
    • September 21st, 2009

    Hi there. I’m trying to find a code for a Portuguese city called “Ponta Delgada”. Since the script gets information by zip code and European zip codes are different, do you know how can i find a zip for a european country that works with google wheater api ?

    I’ve tryed using the yahoo zip code of my city but didn’t worked :)

    • Ashwin Surajbali
    • September 21st, 2009

    Hey, it supports a lot more functionality than I’ve included in this class. I will update it to accept the other features as soon as I get some free time. In the mean time, take a look at this blog

    http://blog.emerick.org/2008/05/07/google-weather-api-feed-documentation/

    • Ashwin Surajbali
    • June 2nd, 2009

    Looks good, thanks for the update :)

    Curl is a plugin you have to enable btw…but file_get_contents is good as well. If you use file_get_contents, you might want to set the user agent ini_set(“user_agent”, “Your browsername here”); just incase.

  1. With your code I had two problems: the cache enabled but no file, it does not return anything. So I have changed your example and the cache is handled by make_request(). The grabbing is made by file_get_contents() as I couldn’t find the curl thing. The other problem is your example doesn’t handle languages, so I’ve included in the get_weather_data() function as an optional parameter.


    < ?php

    /**
    * Grabs weather data from Google.com's weather API and return a nicely formatted array
    *
    * @author Ashwin Surajbali
    * @package Redink Design
    * @version 0.9.2
    *
    * @example
    * $w = new googleWeather();
    * $w->enable_cache = 1;
    * $w->cache_path = '/var/www/mysite.com/cache';
    * $ar_data = $w->get_weather_data(10027);
    * print_r($ar_data);
    * echo $ar_data['forecast'][0]['day_of_week'];
    *
    * Requires PHP 5 or greater
    *
    */

    class googleWeather{

    /**
    * Search Value
    *
    * @var str
    */
    public $search;

    /**
    * Disable or enable caching
    *
    * @var boolean
    */
    public $enable_cache = 0;

    /**
    * Path to your cache directory
    * eg. /www/website.com/cache
    *
    * @var string
    */
    public $cache_path = '';

    /**
    * Cache expiration time in seconds
    * Default: 3600 = 1 Hour
    * If the cached file is older than 1 hour, new data is fetched
    *
    * @var int
    */
    public $cache_time = 3600; // 1 hour

    /**
    * Full location of the cache file
    *
    * @var string
    */
    private $cache_file;

    /**
    * Location of the google weather api
    *
    * @var string
    */
    private $gweather_api_url = 'http://www.google.com/ig/api?hl=%s&weather=%s';

    /**
    * Storage var for data returned from curl request to the google api
    *
    * @var string
    */
    private $raw_data;

    /**
    * Pull weather information for 'Zipcode' or 'City' passed in
    * If enable_cache = true, data is cached and refreshed every hour
    * Weather data is returned in an associative array
    *
    * @param int $zip
    * @return array
    */
    public function get_weather_data($search, $lang="en"){
    $this->search = $search;

    if ($this->search == 0 || strlen($this->search) < 5 || !is_numeric($this->search)){
    $this->city = $this->search;
    } else {
    $this->zip = $this->search;
    };

    $this->cache_file = $this->cache_path . '/' . $this->search;

    // build the url
    $this->gweather_api_url = sprintf($this->gweather_api_url, $lang, urlencode($this->search));

    if ($this->make_request()){

    $xml = new SimpleXMLElement($this->raw_data);
    $return_array = array();

    $return_array['forecast_info']['city'] = $xml->weather->forecast_information->city['data'];
    $return_array['forecast_info']['zip'] = $xml->weather->forecast_information->postal_code['data'];
    $return_array['forecast_info']['date'] = $xml->weather->forecast_information->forecast_date['data'];
    $return_array['forecast_info']['date_time'] = $xml->weather->forecast_information->current_date_time['data'];

    $return_array['current_conditions']['condition'] = $xml->weather->current_conditions->condition['data'];
    $return_array['current_conditions']['temp_f'] = $xml->weather->current_conditions->temp_f['data'];
    $return_array['current_conditions']['temp_c'] = $xml->weather->current_conditions->temp_c['data'];
    $return_array['current_conditions']['humidity'] = $xml->weather->current_conditions->humidity['data'];
    $return_array['current_conditions']['icon'] = 'http://www.google.com' . $xml->weather->current_conditions->icon['data'];
    $return_array['current_conditions']['wind'] = $xml->weather->current_conditions->wind_condition['data'];

    for ($i = 0; $i < count($xml->weather->forecast_conditions); $i++){
    $data = $xml->weather->forecast_conditions[$i];
    $return_array['forecast'][$i]['day_of_week'] = $data->day_of_week['data'];
    $return_array['forecast'][$i]['low'] = $data->low['data'];
    $return_array['forecast'][$i]['high'] = $data->high['data'];
    $return_array['forecast'][$i]['icon'] = 'http://img0.gmodules.com/' . $data->icon['data'];
    $return_array['forecast'][$i]['condition'] = $data->condition['data'];
    }

    }

    return $return_array;

    }

    private function load_from_cache(){
    if ($this->enable_cache){
    if (file_exists($this->cache_file)){
    $file_time = filectime($this->cache_file);
    $now = time();
    $diff = ($now-$file_time);

    if ($diff < = 3600){
    return file_get_contents($this->cache_file);
    }
    }
    }
    }

    private function write_to_cache($data){
    if ($this->enable_cache) {
    if (!file_exists($this->cache_path)){
    // attempt to make the dir
    mkdir($this->cache_path, 0777);
    }
    if (!file_put_contents($this->cache_file, $data)){
    echo "
    Could not save data to cache. Please make sure your cache directory exists and is writable.
    ";
    }
    };
    }

    private function make_request(){
    /*
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_URL, $this->gweather_api_url);
    curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
    curl_setopt ($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    $this->raw_data = curl_exec ($ch);
    curl_close ($ch);
    */

    $data = $this->load_from_cache();
    if (!empty($data)) {
    $this->raw_data=$data;
    return true;
    } else {
    $this->raw_data = file_get_contents($this->gweather_api_url);
    if (empty($this->raw_data)){
    return false;
    } else {
    $this->raw_data=str_replace('< ?xml version="1.0"?>', '< ?xml version="1.0" encoding="ISO-8859-1"?>', $this->raw_data);
    $this->write_to_cache($this->raw_data);
    return true;
    };
    };

    }

    }

    ?>

  2. Ah!!! and somthing else: in this Google API you can enter zips or citys, so I added the idea

  3. Using some of Tristan’s work, i modified the class so, from the original, it solves:

    • changed the old numeric-only zipcode var to a string var ($this->search), thus allowing the usage of google weahter’s supported search strings.
    • cache_time was not being considered in the code, now it is
    • added language support as a class property ($this->language)
    • cache file autogeneration using base64_encode to avoid encoding problems with filesystems
    • new class property ($this->cache_file_encoding) to set cache file encoding (defaults to ISO-8859-1)
    • moved the gweather icons url string to a class property ($this->gweather_icons_url) for faster modification and easier usage
    • filtered all vars used as url parameters using urlencode() function to avoid errors

    There it goes:


    < ?php

    /**
    * Grabs weather data from Google.com's weather API and return a nicely formatted array
    *
    * @author Ashwin Surajbali
    * @package Redink Design
    * @version 0.9.2
    *
    * @example
    * $w = new googleWeather();
    * $w->enable_cache = 1;
    * $w->cache_path = '/var/www/mysite.com/cache';
    * $ar_data = $w->get_weather_data(10027);
    * print_r($ar_data);
    * echo $ar_data['forecast'][0]['day_of_week'];
    *
    * Requires PHP 5 or greater
    *
    */

    class googleWeather{

    /**
    * Search string: zip code; city name; city name, state; city name, country; latitude/longitude or possibly other (Google dependant)
    *
    * @var string
    */
    public $search;

    /**
    * Language (examples: "en", "ca", "da", "de", "es", "fi", "fr", "it", "ja", "ko", "nl", "no", "pt-BR", "ru", "sv", "zh-CN", "zh-TW")
    *
    * @var string
    */
    public $language = '';

    /**
    * Disable or enable caching
    *
    * @var boolean
    */
    public $enable_cache = 0;

    /**
    * Path to your cache directory
    * eg. /www/website.com/cache
    *
    * @var string
    */
    public $cache_path = '';

    /**
    * Cache expiration time in seconds
    * Default: 3600 = 1 Hour
    * If the cached file is older than 1 hour, new data is fetched
    *
    * @var int
    */
    public $cache_time = 3600; // 1 hour

    /**
    * Full location of the cache file
    *
    * @var string
    */
    private $cache_file;

    /**
    * Cache file encoding
    *
    * @var string
    */
    private $cache_file_encoding = 'ISO-8859-1';

    /**
    * Location of the google weather api
    *
    * @var string
    */
    private $gweather_api_url = 'http://www.google.com/ig/api?weather=';

    /**
    * Location of the google weather icons
    *
    * @var string
    */
    private $gweather_icons_url = 'http://img0.gmodules.com';

    /**
    * Storage var for data returned from curl request to the google api
    *
    * @var string
    */
    private $raw_data;

    /**
    * Pull weather information for 'Search' passed in
    * If enable_cache = true, data is cached and refreshed every hour
    * Weather data is returned in an associative array
    *
    * @param int $search
    * @return array
    */
    public function get_weather_data($search = 0) {

    if (empty($search)) {
    die('You must provide one of the following: a zip code (10001); city name (Ontario), city name, state (Ontario,OR); city name, country (London,England); latitude/longitude(,,,30670000,104019996) or possibly other.');
    } else {
    $this->search = $search;
    }

    $this->cache_file = $this->cache_path . '/' . base64_encode($this->search);

    // build the url
    $this->gweather_api_url = $this->gweather_api_url . urlencode($this->search) . '&hl=' . urlencode($this->language);

    if ($this->make_request()) {

    $xml = new SimpleXMLElement($this->raw_data);

    $return_array = array();

    $return_array['forecast_info']['city'] = $xml->weather->forecast_information->city['data'];
    $return_array['forecast_info']['zip'] = $xml->weather->forecast_information->postal_code['data'];
    $return_array['forecast_info']['date'] = $xml->weather->forecast_information->forecast_date['data'];
    $return_array['forecast_info']['date_time'] = $xml->weather->forecast_information->current_date_time['data'];

    $return_array['current_conditions']['condition'] = $xml->weather->current_conditions->condition['data'];
    $return_array['current_conditions']['temp_f'] = $xml->weather->current_conditions->temp_f['data'];
    $return_array['current_conditions']['temp_c'] = $xml->weather->current_conditions->temp_c['data'];
    $return_array['current_conditions']['humidity'] = $xml->weather->current_conditions->humidity['data'];
    $return_array['current_conditions']['icon'] = 'http://www.google.com' . $xml->weather->current_conditions->icon['data'];
    $return_array['current_conditions']['wind'] = $xml->weather->current_conditions->wind_condition['data'];

    for ($i = 0; $i < count($xml->weather->forecast_conditions); $i++) {
    $data = $xml->weather->forecast_conditions[$i];
    $return_array['forecast'][$i]['day_of_week'] = $data->day_of_week['data'];
    $return_array['forecast'][$i]['low'] = $data->low['data'];
    $return_array['forecast'][$i]['high'] = $data->high['data'];
    $return_array['forecast'][$i]['icon'] = $this->gweather_icons_url . '/' . $data->icon['data'];
    $return_array['forecast'][$i]['condition'] = $data->condition['data'];
    }

    }

    return $return_array;

    }

    private function load_from_cache() {

    if ($this->enable_cache) {
    if (file_exists($this->cache_file)) {
    $file_time = filectime($this->cache_file);
    $now = time();
    $diff = ($now-$file_time);
    if ($diff < = $this->cache_time) {
    return file_get_contents($this->cache_file);
    }
    }
    }

    }

    private function write_to_cache() {

    if ($this->enable_cache) {
    if (!file_exists($this->cache_path)) {
    // attempt to make the dir
    mkdir($this->cache_path, 0777);
    }
    if (!file_put_contents($this->cache_file, $this->raw_data)) {
    echo "

    Could not save data to cache. Please make sure your cache directory exists and is writable.

    ";
    }
    }

    }

    private function make_request() {

    $data = $this->load_from_cache();
    if (!empty($data)) {
    $this->raw_data=$data;
    return true;
    } else {
    $this->raw_data = file_get_contents($this->gweather_api_url);
    if (empty($this->raw_data)) {
    return false;
    } else {
    $this->raw_data=str_replace('< ?xml version="1.0"?>', '< ?xml version="1.0" encoding="'.$this->cache_file_encoding.'"?>', $this->raw_data);
    $this->write_to_cache();
    return true;
    }
    }

    }

    }

    ?>

    Usage example:


    < ?php

    // google weather
    require_once('php/google_weather_cache.php');
    $w = new googleWeather();
    $w->language = 'ca';
    $w->enable_cache = 1;
    $w->cache_path = '/absolute/path/to/google_weather_cache/';
    $w->cache_file_encoding = 'UTF-8';
    $weather_data = $w->get_weather_data('Barcelona');

    ?>

    • Ashwin Surajbali
    • October 6th, 2009

    This is great, thank you!

    • Matt
    • May 26th, 2011

    Google recently changed their weather icons. If you use this script and notice that the icons aren’t showing up all you need to do is change line 115 to this:

    $return_array['current_conditions']['icon'] = $xml->weather->current_conditions->icon['data'];

    I guess it no longer requires that appended URL, I don’t use forecast on my website but you’ll probably have to change the icon line for that as well.

    $return_array['forecast'][$i]['icon'] = $data->icon['data'];

    Also thanks for the script Ashwin!

    • admin
    • May 26th, 2011

    Thanks Matt, I just realized this change today as well. I will update the code.

    Matt :
    Google recently changed their weather icons. If you use this script and notice that the icons aren’t showing up all you need to do is change line 115 to this:
    $return_array['current_conditions']['icon'] = $xml->weather->current_conditions->icon['data'];
    I guess it no longer requires that appended URL, I don’t use forecast on my website but you’ll probably have to change the icon line for that as well.
    $return_array['forecast'][$i]['icon'] = $data->icon['data'];
    Also thanks for the script Ashwin!

    • Tomako
    • June 28th, 2011

    what about this


    if ($diff <= 3600){ ….

    should be


    if ($diff cache_time){ ….

    • Tomako
    • June 28th, 2011

    if ($diff cache_time){

    • Tomako
    • June 28th, 2011

    if ($diff <= $this->cache_time){

    (dammend textprocessor)

    • admin
    • June 28th, 2011

    @Tomako

    Good catch! Code updated, thanks.

    • Paulb
    • December 9th, 2011

    @admin

    Would it be poss to help change it so i could use city name instead as im in the uk and we dont use zip code?

  1. No trackbacks yet.