Json data feeds and cURL


I recently did a project where I implemented a weather feed from opensnow.com.  Turns out working with json is actually pretty easy once you understand the data structure.  Now, I will admit that I initially thought I would do the task using the JavaScript Fetch API

var myList = document.querySelector('ul');

    fetch('snowreport.json')
    .then(function(response) {
      if (!response.ok) {
        throw new Error("HTTP error, status = " + response.status);
      }
      return response.json();
    })
    .then(function(json) {
      for(var i = 0; i < json.current.length; i++) {
        var listItem = document.createElement('li');
        listItem.innerHTML = '<strong>' + json.current.temp + '</strong>';
        myList.appendChild(listItem);
      }
    })
    
    .catch(function(error) {
      var p = document.createElement('p');
      p.appendChild(
        document.createTextNode('Error: ' + error.message)
      );
      document.body.insertBefore(p, myList);
    });

but I ran into a CORS (Cross-origin resource sharing) issue and then also realized that JS would expose the client’s API Key, so I moved my solution into PHP using a cURL function.

Now, I am not sure that exposing the client key was an issue, but I did read that they were allowed 1000 requests per month and if someone wanted they could grab and use the api key causing the limit to be reached way too soon…  So, putting it in PHP was the safer route to take.

function CallAPI($method, $url, $data = false) {
    $curl = curl_init();

    switch ($method)
    {
        case "POST":
            curl_setopt($curl, CURLOPT_POST, 1);

            if ($data)
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            break;
        case "PUT":
            curl_setopt($curl, CURLOPT_PUT, 1);
            break;
        default:
            if ($data)
                $url = sprintf("%s?%s", $url, http_build_query($data));
    }

    /* Optional Authentication:
    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($curl, CURLOPT_USERPWD, "username:password"); */

    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

    $result = curl_exec($curl);

    curl_close($curl);

    return $result;
};

$results = CallApi( 'GET', 'https://opensnow.com/publicapi/2.0/{Client Key}/locations/6');
$results = json_decode($results, true);

After getting the feed, it was just a matter of figuring out how to echo it out to the screen and for the weather, I used a foreach because there was 5 days worth of the data and it included day and night and 4-5 stats per each would have meant approximately 100 or more echo statements. The foreach was much easier and faster.  I also did a unix timestamp conversion to get the actual day of the week spelled out vs. numeric…

foreach ( $results['0']['forecast']['daily'] as $daily ){
            // date in a string format
            $date = $daily['date'];

            //Convert the date string into a unix timestamp.
            $unixTimestamp = strtotime($date);

            //return just the day full name of the day using PHP's date function.
            $dayOfWeek = date("l", $unixTimestamp);
            echo '<div class="column-fifth">';
            echo 'Date: ' . $daily['date'] . '<br>';
            echo '<p><strong>' . $dayOfWeek . ' Night</strong></p>';
            echo '<img src="' . $daily['night']['icon'] . '" style="max-width:100px;"> <br>';
            echo 'High: ' . $daily['night']['temp'] . '<br>';
            echo 'Snow: ' . $daily['night']['snow'] . '<br>';
            echo $daily['night']['weather'] . '<br>';
            echo 'Wind Speed: ' . $daily['night']['wind']['speed'] . '<br>';
            echo 'Wind Direction: ' . $daily['night']['wind']['direction'] . '<br>';
            echo 'Wind Gusts: ' . $daily['night']['wind']['gust'] . '<br>';
            echo 'Snow Level: ' . $daily['night']['snow_level'] . '<br>';
            echo 'Cloud Cover: ' . $daily['night']['cloud_cover'] . '<br>';
            echo '</div>';
        };