Live weather data using a simple database and Statamic CMS

Back to all journal posts

There's a weather station somewhere, checking on the local surf weather and noting it down in a database. Our client wanted to display that data on their new site, and luckily for us, the setup was a breeze with Statamic.

What we needed to do

Once the weather station had done its thing for a short while and we'd collected some actual data to work with, it became a case of getting that on the site. We needed to do three things to get what we want:

  1. Connect to the weather station db
  2. Fetch the relevant data
  3. Display that data

Connecting to the DB

Because Stamic uses a flat file architecture, it doesn't really have any need for a database - or so you'd think. However the guys at Statamic have built in support for a large user-base, and for those people that want to have their users in a database. So there's our connection sorted.

Statamic makes great use of the .env file and setting multiple environments is easy. It's in the .env file where we'll add our connection info, and the type of db we're using (mysql in our case).

DB_CONNECTION=mysql 
DB_HOST= 
DB_PORT= 
DB_DATABASE= 
DB_USERNAME= 
DB_PASSWORD=

Statamic loads this data by default, ready to use with Laravel's Eloquent.

Fetching the data

To make things simple, we created a new Addon to keep it all in one place. And we gave it a cool name - WindFinder. Our WindFinder.php file looks something like this

<?php

namespace Statamic\Addons\WindFinder;

use Cache;
use Illuminate\Database\Eloquent\Model;

class WindFinder extends Model
{
 protected $table = 'mystation';

 public static function data($column = null)
 {
    $data = Cache::remember('all', 1, function () {
      return self::all()->last();
    });

    if ($data) {
      if ($column) {
        return $data->$column;
      } else {
        return $data;
      }
    } else {
      return null;
    }
  }
}

We're loading in Cache so the server doesn't get all flustered...

use Cache;

And we're also loading in Eloquent, so we can work with the DB really easily...

use Illuminate\Database\Eloquent\Model;

We chose the right table from the connection we set up earlier:

protected $table = 'mystation';

Our data function is what will actually grab the data, we'll pass in the $column we're looking for and return it if it exists.

public static function data($column = null) { ... }

Before we make a call to the DB, we check to see if our cached data already exists and if it doesn't we get the last row (we're only interested in current, not past records) in the database and add it to the cache for 1 min. Although we want the WindFinder to be real time, we still need to cache it a little, just incase the server can't cope with all the surfers dying to find out the weather.

$data = Cache::remember('all', 1, function () {
  return self::all()->last();
});

Then it's just a case of returning the right table column, or everything (or nothing).

if ($data) {
  if ($column) {
    return $data->$column;
  } else {
    return $data;
  }
} else {
  return null;
}

Simple right? Now we just have to display it.

Displaying the data

Because we're using this data in a bunch of places throughout the site and we don't always need all the data, it makes sense to build some simple tags to get certain bits of data (or all of it). Next to our WindFinder.php file, we've got a WindFinderTags.php:

<?php

namespace Statamic\Addons\WindFinder;

use Statamic\Extend\Tags;

class WindFinderTags extends Tags
{
  public function all()
  {
    return WindFinder::data();
  }

  public function speed()
  {
    return WindFinder::data('WindAvgSpeedCur');
  }

  // etc...
}

This time we're extending Statamic's Tags so we can use them in templates super easily.

use Statamic\Extend\Tags;

Our first function grabs everything, so on the page where we display it all we're not making multiple calls.

public function all()
{
  return WindFinder::data();
}

Then our second function (and the rest, but for different things) allow us to just fetch that specific piece of data, this one for instance gets us the Current Average Wind Speed. We just fire off the relevant column we're looking for to our data model and it returns that column from the most recent db call.

public function speed()
{
  return WindFinder::data('WindAvgSpeedCur');
}

Then in our templates we just use a Tag to display that data:

{{ wind_finder:speed }} Knots / {{ wind_finder:direction }}

This is what makes Statamic a great CMS to work with, as it's built on top of Laravel you have access to Laravel inside Addons and Helpers, so things like this become nice and easy to work with. Statamic's Tag system also makes using your Addons inside of templates nice and simple too.