Skip to main content

A primitive request-and-cache function for PHP that checks for fresh content in the cache and retrieves content from a source if fresh content isn't available.

<?php

/**
 * Gets the contents of a file if it exists, otherwise grabs and caches.
 *
 * @author david walsh
 * @link http://davidwalsh.name/php-cache-function
 *
 * @param string $file The file to grab content from. If the file
 *                      doesn't exist, the file is created and
 *                      content placed into.
 * @param string $url The URL to get content from if cached
 *                      content isn't fresh.
 * @param number $hours Hours before content expires.
 * @param string $fn A function name to pass the freshly received
 *                      content to.
 * @param string $fn_args Arguments to pass to the third argument's function.
 * @return string The content
 */
function get_content ($file, $url, $hours = 24, $fn = '', $fn_args = '')
{
    // vars
    $current_time = time();
    $expire_time = $hours * 60 * 60;
    $file_time = filemtime($file);

    // decisions, decisions
    if (file_exists($file) && ($current_time - $expire_time < $file_time)) {

        // echo 'returning from cached file';
        return file_get_contents($file);
    } else {

        $content = get_url($url);

        if ($fn) {
            $content = $fn($content, $fn_args);
        }

        $content .= '<!-- cached:  ' . time() . '-->';

        file_put_contents($file, $content);

        // echo 'retrieved fresh from '.$url.':: '.$content;
        return $content;
    }
}

/**
 * Gets content from a URL via curl.
 *
 * @param string $url
 * @return mixed
 */
function get_url ($url)
{
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);

    $content = curl_exec($ch);
    curl_close($ch);

    return $content;
}

/*
 * Usage example
 *
 * Retrieves my Twitter follower count, parses the code, and caches the
 * content for three hours.
 *
 * There are several more advanced PHP caching classes available but
 * the simple function above covers most of my needs -- hopefully
 * it can help you out too!
 *
 * */
$TWITTER_FOLLOWERS_FILE_NAME = 'twitter-followers.txt';
$TWITTER_FOLLOWERS_URL = 'http://twitter.com/users/show.json?screen_name=davidwalshblog';

$TWITTER_FOLLOWERS = get_content($TWITTER_FOLLOWERS_FILE_NAME, $TWITTER_FOLLOWERS_URL, 3, 'format_followers', array(
    'file' => $TWITTER_FOLLOWERS_FILE_NAME
));

/* utility function */
function format_followers ($content, $args)
{
    $content = json_decode($content);
    $twitter_subscribers = $content->{'followers_count'};

    if ($twitter_subscribers) {
        $twitter_subscribers = number_format($twitter_subscribers, 0, '', ',');
        file_put_contents($args['file'], $twitter_subscribers);

        return $twitter_subscribers;
    }
}

?>