Skip to Content
Course content

64: Practice Exercise: Building a File-Based Caching Layer

Click on the "Edit" button in the top corner of the screen to edit your slide content.

How do I handle the expiration logic so the data doesn't stay stale forever?

This is the core of any caching system: the TTL (Time To Live). If you just check if a file exists, you've built a permanent archive, not a cache. I usually handle this by comparing the current time against the file's last modification time using filemtime().

Here is a quick way to structure that check. I'm using a 3600-second (one hour) window here:

$cacheFile = 'cache/product_list.json';
$ttl = 3600; 

if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $ttl)) {
    // The file exists and it's fresh enough. Use it.
    $data = file_get_contents($cacheFile);
} else {
    // Data is missing or too old. Go fetch it from the slow API.
    $data = fetchSlowProductData(); 
    file_put_contents($cacheFile, $data);
}

One thing to keep in mind: filemtime() results are cached by PHP for performance. If you're doing extremely high-frequency updates to the same file, you might need to call clearstatcache(), but for a standard API cache, you probably won't need to worry about it.

What's the best way to store complex data like arrays without losing the structure?

Since file_put_contents expects a string, you can't just throw a PHP array at it. You have two real choices: serialize() or json_encode(). I almost always lean toward JSON. It's slightly slower than native serialization, but it's human-readable, which makes debugging your cache files a thousand times easier.

If you're caching a result set from a database or a REST API, do it like this:

// Saving the data
$productData = ['id' => 101, 'name' => 'Mechanical Keyboard', 'price' => 120];
file_put_contents($cacheFile, json_encode($productData));

// Retrieving the data
$raw = file_get_contents($cacheFile);
$productData = json_decode($raw, true); // 'true' converts it back to an associative array

Just be careful with the json_decode second parameter. If you forget true, you'll get a stdClass object back instead of an array, which might break the rest of your code if you're expecting array syntax.

How do I turn a dynamic query or URL into a valid filename?

You can't use a URL or a SQL query as a filename because they contain characters like /, ?, and & that the filesystem will hate. To solve this, I use a hashing algorithm. md5() is perfect for this; it's fast, and while it's not secure for passwords, it's more than enough for generating a unique cache key.

Imagine you're caching results for different category pages. You can't name a file /api/products?category=electronics. Instead, do this:

$apiUrl = "https://api.example.com/products?category=electronics&sort=price_asc";
$cacheKey = md5($apiUrl); // Returns something like '8f92b... '
$filename = "cache/" . $cacheKey . ".json";

if (file_exists($filename)) {
    // Load cache...
}

By hashing the entire request string, you ensure that if the user changes the sort order or the category, they get a different cache file, preventing "leaked" data from one request showing up in another.




📋 Practical Task

Practical Exercise: Building a Cached External Weather API Wrapper

Your goal is to create a script that fetches weather data for a specific city from a mock API (or a real one if you have a key) and caches the result to avoid hitting the API on every page load.

  • The Setup: Create a folder named cache/ in your project directory and ensure it is writable.
  • The Logic:
    • Define a city name (e.g., "London") as a variable.
    • Generate a unique filename for that city using md5().
    • Implement a TTL of 10 minutes (600 seconds).
    • If the cache is valid, load the data from the file.
    • If the cache is expired or missing, simulate an API call (using file_get_contents on a URL or simply creating a fake array of weather data), then save that data as a JSON file.
  • The Verification: Print a message to the screen stating whether the data was "Loaded from Cache" or "Fetched from API". Refresh the page a few times to confirm it only hits the "API" once every 10 minutes.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.