Archived post from 2013. Kept for reference; the technology is outdated.

Auto-generated cache.manifest in PHP

4 min read

If you don’t want to read the entire entry, you can get the code (and propose changes, of course) on GitHub: https://github.com/tx2z/autogenerated-cache.manifest-php

A very interesting thing in HTML5 is the possibility of create offline applications or web pages through the cache.manifest file. These pages can be read by the user when he doesn’t have an Internet connection, that today, with the poor mobile network coverage in some places, is something usual. It’s also a good idea with good connections because the user doesn’t have to download all the data and the page load will be faster.

So, yes, really interesting, but if you have tried to create a cache.manifest on your own it takes time and effort, because you have to update it every time you add or change a file in your web or app.

For this reason I looked for an easy, or better, automatic, way to generate this file and I’ve found that is really easy with PHP (surely it is also possible with other server-side languages).

Take a look at the code to see how easy it is:

 1<?php
 2// Add the correct Content-Type for the cache manifest
 3header('Content-Type: text/cache-manifest');
 4
 5// Write the first line
 6echo "CACHE MANIFEST\n";
 7
 8// Initialize the $hashes string
 9$hashes = "";
10
11function create_manifest($folder) {
12  $dir = new RecursiveDirectoryIterator($folder);
13	// Iterate through all the files/folders in the current directory
14	foreach (new RecursiveIteratorIterator($dir) as $file) {
15		$info = pathinfo($file);
16
17		// If the object is a file
18		// and it's not called manifest.php (this file),
19		// and it's not a dotfile, add it to the list
20		if ($file -&gt; IsFile() && $file != "./manifest.php" && substr($file -&gt; getFilename(), 0, 1) != ".") {
21			// Replace spaces with %20 or it will break
22			echo str_replace(' ', '%20', $file) . "\n";
23
24			// Add this file's hash to the $hashes string
25			$hashes .= md5_file($file);
26		}
27	}
28}
29
30create_manifest(".");
31
32// Write the $hashes string 
33echo "# Hash: " . md5($hashes) . "\n";
34?>

I think it needs little explanation, but:

– First we declare that the file is a cache.manifest and write “CACHE MANIFEST” in the first line:

1<?php
2// Add the correct Content-Type for the cache manifest
3header('Content-Type: text/cache-manifest'); 
4
5// Write the first line
6echo "CACHE MANIFEST\n";
7?>

– Almost everything is done in the function “create_manifest” that iterates through all the files/folders of the folder defined in the variable $folder.

Inside the function we create an array, $dir, that contains all the files/folders, thanks to the class “RecursiveDirectoryIterator“. We “foreach” this array and get the path of every file with “pathinfo“.

Then, if the object is a file (not a folder) and it’s not called manifest.php (because if you cache your manifest file you’re gonna have a bad time), and it’s not a “dotfile”, we print it into the page, replacing spaces with %20 (in theory that’s not necessary, because you have created your URLs and files in a proper way 🙂 ).

Finally, we add the md5 hash of the file into the $hashes variable (I will explain that later)

 1<?php
 2function create_manifest($folder) {
 3  $dir = new RecursiveDirectoryIterator($folder);
 4  // Iterate through all the files/folders in the current directory
 5	foreach (new RecursiveIteratorIterator($dir) as $file) {
 6		$info = pathinfo($file);
 7
 8		// If the object is a file
 9		// and it's not called manifest.php (this file),
10		// and it's not a dotfile, add it to the list
11		if ($file -&gt; IsFile() && $file != "./manifest.php" && substr($file -&gt; getFilename(), 0, 1) != ".") {
12			// Replace spaces with %20 or it will break
13			echo str_replace(' ', '%20', $file) . "\n";
14
15			// Add this file's hash to the $hashes string
16			$hashes .= md5_file($file);
17		}
18	}
19}
20?>

– It remains to call the function in the folder whose files we want to add into the cache.manifest file. We can add a point(.) if we want to include all.

1<?php
2create_manifest(".");
3?>

– Finally, if we change the content of a file without changing his name (we update an image for example) the browser doesn’t know if the file has changed and it is going to use the cached version of the file. But if the cache.manifest has changed it is going to download again all the files.

Printing the $hashes variable (that is different every time a file changes) we make sure that the browser is going to download all the files if we change anything.

1<?php
2// Write the $hashes string
3echo "# Hash: " . md5($hashes) . "\n";
4?>

And that’s it. It only remains to add it to our web page after the doctype declaration:

1<!DOCTYPE html>
2<html manifest="manifest.php">

We have an auto-generated cache.manifest file that we don’t need to update every time 🙂

It works, for example, in the Revista Exégesis tablet version: http://www.revista-exegesis.com/publicaciones/2059/