Weather in WordPress with Dark Sky

weather-tileUpdate 1-4-17: Forecast.io is now called Dark Sky. Classes, names, and such have been updated in this post and the various gists/repo.

A recent project called for a “current weather” tile on the homepage. A quick look through the available weather APIs out there lead me to Forecast.io DarkSky.net, which is pretty slick. There are more than a few PHP approaches already put together. I took Guilherm Uhelski’s PHP helper class and expanded it for WordPress.

The purpose of this helper class is to: perform the API call, process and return the JSON response, and store that response for quick reuse. Check out here. Feel free to drop it into a custom plugin for use on your site or your projects.

WP-DarkSky uses the WordPress HTTP API helper functions (as well as transients). If you’re not familiar with external HTTP calls or WordPress’ helper functions, check out this great series of walkthroughs by Tom McFarlin. Here’s a good walk-through on transients. With a good understanding of the HTTP API and transients, this class will be pretty straight-forward.

Next up, sign up for a free account and API key from DarkSky.net, you’ll need that in order to use this helper class.

Okay, now that we’ve got the basics out of the way, let’s use it!

Using It

Here’s a quick example on using this class. At the bare minimum you need an API key, a Latitude, and a Longitude.

<?php
/**
* Basic example of WP-DarkSky useage.
*
* @since 01-04-2017 - Updated for new Dark Sky API & Naming
*
* @link https://github.com/joshuadavidnelson/wp-darksky
* @author Joshua David Nelson, [email protected]
*/
$args = array(
'api_key' => '', // Enter your API key
'latitude' => '', // enter the longitude
'longitude' => '', // enter the latitude
);
$forecast = new DarkSky\Forecast( $args );
// Get the response, which will be an array similar to this one: https://gist.github.com/joshuadavidnelson/b27ff69e9a99c1500a89
$response = $forecast->get_response();

Then, it’s a simple matter of calling the elements you need out of the response. Using the magic __get() method, all of the response data is available to call.

Familiarize yourself with the typical response, and the Dark Sky API. From there you can take the response data and build some cool things.

In my case, I wanted today’s minimum and maximum temperatures. Here’s a basic version of the function I use in my template:

<?php
/**
* Basic example of WP-DarkSky used to output the current day's min/max temperatures in fahrenheight.
*
* @since 01-04-2017 - Updated for new Dark Sky API & Naming
*
* @link https://github.com/joshuadavidnelson/wp-darksky
* @author Joshua David Nelson, [email protected]
*/
$args = array(
'api_key' => '', // Enter your API key
'latitude' => '', // enter the longitude
'longitude' => '', // enter the latitude
'query' => array( 'units' => 'us', 'exclude' => 'flags' )
);
$forecast = new DarkSky\Forecast( $args );
// Get the current forecast data for the daily forecast, which provides the next 7 days
$daily = isset( $forecast->daily['data'] ) ? $forecast->daily['data'] : false;
// Pull out the current day's forecast
if( $daily ) {
$date_format = 'n/j/Y'; // format used to compare dates
$time_now = date( $date_format, current_time( 'timestamp' ) );
foreach( $daily as $day ) {
if( isset( $day['time'] ) && $time_now == date( $date_format, $day['time'] ) ) {
echo number_format( $day['temperatureMin'], 0 ) . ' / ' . number_format( $day['temperatureMax'], 0 );
break; // Breaking the foreach here because we found today's forecast, no need to loop through any more
}
}
}

How it Works

Using the great HTTP API functions in WordPress, the helper class grabs the API response. It’s then stored in a transient (by default, but this can be overridden – see below), allowing us to store the response for quick recall later. This is important from a page load standpoint, of course, but also critical with services like Dark Sky, which provides 1,000 free calls per day.

It makes sense to grab the forecast once for a set period of time, rather than at every page load. If the latter is true, you could end up with quite a lot of calls to the API and quickly reach your free limit.

For my purposes I only needed the daily forecast, so a 6-hour cache is sufficient (it could be set to 24, but 6 hours allows for 4 API calls a day and accounts for potential changes in the forecast). If you needed, for instance, the current weather, then you could easily reduce the transient time to 5 minutes and still keep your calls below the 1,000/day limit.

Need a fresh of the API call? Just use the get_response function with the first parameter set to true clear the cache and get a fresh API response:

<?php
/**
* Basic example of WP-DarkSky useage with a refreshed response.
*
* @since 01-04-2017 - Updated for new Dark Sky API & Naming
*
* @link https://github.com/joshuadavidnelson/wp-darksky
* @author Joshua David Nelson, [email protected]
*/
$args = array(
'api_key' => '', // Enter your API key
'latitude' => '', // enter the longitude
'longitude' => '', // enter the latitude
);
$forecast = new DarkSky\Forecast( $args );
// Fresh response, clear the cache with the 'true' parameter
$response = $forecast->get_response( true ); // If the parameter is false or not set, it will use the cache.

You can modify the other cache settings in the initial arguments or by setting the specific parameter, as shown below:

<?php
/**
* Basic example of WP-DarkSky useage and available caching parameters. Below the defaults are shown.
*
* @since 01-04-2017 - Updated for new Dark Sky API & Naming
*
* @link https://github.com/joshuadavidnelson/wp-darksky
* @author Joshua David Nelson, [email protected]
*/
$args = array(
'api_key' => '', // Enter your API key
'latitude' => '', // enter the longitude
'longitude' => '', // enter the latitude
'cache_prefix' => 'api_', // careful here, md5 is used on the request url to generate the transient name. You are limited to an 8 character prefix before the combined total exceeds the transient name limit
'cache_enabled' => true, // Enable the cache, or false to skip caching entirely
'cache_time' => 6 * HOUR_IN_SECONDS, // the time in seconds to store the
'clear_cache' => false, // set to true to force the cache to clear
);
$forecast = new DarkSky\Forecast( $args );
// Get the response with default parameters
$response = $forecast->get_response();
// Modify a caching parameter, refresh the response. In this case, we're shortening the cache time.
$forecast->cache_time = 5 * MINUTE_IN_SECONDS;
$response = $forecast->get_response( true );

Bonus: Weather Icons

weather-tileYou might notice that the image shown above (and here) include an icon, yet my example code above doesn’t? Oh myyy, you’re observant!

On my project I built another helper class to extend the original DarkSky\Forecast class and add some awesome Weather Icons (by Eric Flowers).

Drop this extra class into the same plugin as the class above to build some awesome weather outputs. To take the temperature example above and expand it, here it is with a weather icon:

<?php
/**
* A helper class for that extends the WP-DarkSky helper class with Weather Icons.
*
* You'll need to add the Weather Icons stylesheet, web fonts, etc and enqueue them correctly.
*
* @see weathericons.io
* @see https://developer.wordpress.org/reference/functions/wp_enqueue_style/
* @see https://darksky.net/dev/docs/
*
* @link https://github.com/joshuadavidnelson/wp-darksky
*
* @since 1.0.0
* @since 1.1.0 - Update for new Dark Sky API (versus old Forecast.io naming)
*
* @author Joshua David Nelson, [email protected]
*/
$args = array(
'api_key' => $api_key, // set your api key
'latitude' => $lat, // set your latitude
'longitude' => $long, // set your longitude
'query' => array( 'units' => 'us', 'exclude' => 'flags' )
);
$forecast = new DarkSky\Weather_Icon_Forecast( $args );
// Get the current forecast for a given latitude and longitude
$daily = isset( $forecast->daily['data'] ) ? $forecast->daily['data'] : '';
$current = '';
$title_attr = '';
if( is_array( $daily ) ) {
$date_format = 'n/j/Y';
$time_now = date( $date_format, current_time( 'timestamp' ) );
foreach( $daily as $day ) {
if( isset( $day['time'] ) && $time_now == date( $date_format, $day['time'] ) ) {
// check the variables are setup
if( isset( $day['temperatureMin'], $day['temperatureMax'] ) && !empty( $day['temperatureMin'] ) && !empty( $day['temperatureMax'] ) ) {
// The temperature output
$current = number_format( $day['temperatureMin'], 0 ) . ' / ' . number_format( $day['temperatureMax'], 0 );
// Set the icon, if there is one
$icon = !empty( $day['icon'] ) ? $forecast->get_icon( esc_attr( $day['icon'] ) ) : '';
// set the title attribute to the forecast summary
$title_attr = !empty( $day['summary'] ) ? ' title="' . esc_attr( $day['summary'] ) . '"' : '';
}
}
}
}
// If we have a valid forecast, we can build the widget
if( ! empty( $current ) )
echo '<div class="widget weather-widget"><h5 class="title" id="weather-widget-title">Today\'s Weather</h5>' . $icon . '<span class="temp">' . $current . ' &deg;</span></div>';

Note that this doesn’t enqueue the Weather Icons stylesheet. You’ll have to do that in your functions.php file. Refer to the Weather Icons Documentation and the wp_enqueue_style function.

Featured Image: Fingers of Heaven by Robert Postma on 500px.com, under Creative Commons License.

Discussion

Leave a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <b> <blockquote cite=""> <cite> <em> <i> <strike> <strong> . If you'd like to include code in your post, please post it to http://gist.github.com and include a link.