Integrate automatic updates to free or premium web applications


Introduction

In this tutorial we'll show you how to check for updates and download a new version in your generic (non-Joomla or WordPress) web based application written in PHP. We will assume that you've already configured your UpdaterCloud update server, created a new product release and that the update channel for your product is accessible. Alternatively, please check the Quickstart guide first.

Checking for updates

To get the latest version details for your app, you'll first need to make a GET request to your Update Channel JSON API endpoint. We will use CURL here, but you can use any HTTP client you want (e.g. Guzzle). The update channel url can be copied from the update channels list in your UpdaterCloud admin panel.

{warning} Make sure to replace the {{SUBDOMAIN}} with your personal UpdaterCloud subdomain and the {{UPDATE_CHANNEL_ID}} with your UpdaterCloud update channel id.

// Initialize the CURL session
$ch = curl_init();

// Set options for CURL transfer
curl_setopt_array($ch, array(
  CURLOPT_URL => "https://{{SUBDOMAIN}}.updatercloud.com/api/v1/update-channels/{{UPDATE_CHANNEL_ID}}.json",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_TIMEOUT => 10,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => array(
    "Accept: application/json"
  ),
));

// Perform the CURL request
$response = @curl_exec($ch);

// Close the CURL session and free all resources
curl_close($ch);

We can improve this code to check for possible errors.

// Handle connection errors (such as an API outage)
// You should show users an appropriate message asking to try again later
if (curl_errno($ch) > 0) {
    throw new Exception("Error connecting to API: " . curl_error($ch));
}

// If we reach this point in the code, we have a proper response!
// Let's get the response code to check if the update channel can be accessed
$responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// HTTP 404 indicates that the update channel doesn't exist
if ($responseCode === 404) {
    throw new Exception("Could not get the latest version details.");
}

// Anything other than HTTP 200 indicates a request or API error
// In this case, you should again ask the user to try again later
if ($responseCode !== 200) {
    throw new Exception("Could not get the latest version details.");
}

If everything went well, we should get a JSON response that looks like this:

{
    "update": {
        "title": "My Awesome Application Updates",
        "name": "Application Name",
        "slug": "application_name",
        "type": "item",
        "short_description": "My awesome application tagline",
        "description": "My awesome application description",
        "changelog": "...",
        "featured_image": null,
        "version": "1.0.0-rc1",
        "maturity": "RC",
        "details_url": "https://example.com",
        "download_url": "https://subdomain.updatercloud.com/downloads/my-awesome-application/8fa6e7e7-1d87-4905-8599-fae52165bc3e/8fb0e947-fb3f-4d45-aab7-5dd0961530dd/download",
        "license": "GPL",
        "license_url": null,
        "homepage": "https://example.com",
        "author": "Your Name",
        "author_homepage": "https://example.com",
        "last_updated": "2020-01-26 23:07:48"
    }
}

We can now parse the response into an array and prepare all needed variables. We're most interested in the version number (so we can compare it with the installed application version) and the download_url (if the installed application version is older than the latest version, we'll use this url to download the latest version).

// Parse the response with warnings supressed
$body = @json_decode($response);

// Check for errors while decoding the response
if ($body === false && json_last_error() !== JSON_ERROR_NONE) {
    throw new Exception("Error parsing the JSON response.");
}

// Now we can get the latest version details
$latestVersion = $body->updates->update->version;
$downloadUrl = $body->updates->update->download_url;

// You need to get the user's download key that will be used to download the latest version.
// You've most probably stored the user provided download key in your application database.
// Only needed for Premium apps
$downloadKey = 'key';

// Your installed application version
$installedVersion = 'your_installed_application_version';

Download the latest version

Once we have all details in place, we can check if the installed version is lower than the version in the update channel JSON feed. If it is, it means an update is available and we should download it.

// The installed version is lower than the latest version from the update channel feed,
// so we should proceed to downloading it.
if (version_compare($latestVersion, $installedVersion, '>')) {
    // Attach the download key to the latest version download url
    $url = $downloadUrl . '?download_key=' . $downloadKey;

    // Set the directory name where the latest version file will be saved
    $dir = './';

    // Set a temporary file name for the downloaded file
    // This is usually your application name
    $fileName = 'your_application_name.zip';

    // Downloaded file location
    $file = $dir . $fileName;

    // Open file  
    $fp = fopen($file, 'wb');

    // Initialize the CURL session
    $ch = curl_init($url);

    // Set options for CURL transfer
    curl_setopt($ch, CURLOPT_FILE, $fp);
    curl_setopt($ch, CURLOPT_HEADER, 0);

    // Perform the CURL request
    @curl_exec($ch);

    // Close the CURL session and free all resources
    curl_close($ch);

    // Close file
    fclose($fp);
}

Perform the application update

Now that you have successfully downloaded the latest version of your application, you can go ahead and perform the actual application update (unzip files, overwrite existing application files, update the application database tables, etc). We can`t provide sample code for that, as this is something that depends entirely on your application and update routine implementation.