Auto-generated cache.manifest in PHP

If you don’t want to read the entire entry, you can get the code (and propose changes, of course) in 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. This pages can be read by the user when he don’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 also with good connections because the user don’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 by 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’ve look for an easy, or better, automatic, way to generate this file and I’ve found that is really easy with PHP (sure that it is also with other server side languages).

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
// Add the correct Content-Type for the cache manifest
header('Content-Type: text/cache-manifest');

// Write the first line
echo "CACHE MANIFEST\n";

// Initialize the $hashes string
$hashes = "";

function create_manifest($folder) {
  $dir = new RecursiveDirectoryIterator($folder);
	// Iterate through all the files/folders in the current directory
	foreach (new RecursiveIteratorIterator($dir) as $file) {
		$info = pathinfo($file);

		// If the object is a file
		// and it's not called manifest.php (this file),
		// and it's not a dotfile, add it to the list
		if ($file -&gt; IsFile() && $file != "./manifest.php" && substr($file -&gt; getFilename(), 0, 1) != ".") {
			// Replace spaces with %20 or it will break
			echo str_replace(' ', '%20', $file) . "\n";

			// Add this file's hash to the $hashes string
			$hashes .= md5_file($file);
		}
	}
}

create_manifest(".");

// Write the $hashes string 
echo "# Hash: " . md5($hashes) . "\n";
?>

I think it need no much explanation but:

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

1
2
3
4
5
6
7
<?php
// Add the correct Content-Type for the cache manifest
header('Content-Type: text/cache-manifest'); 

// Write the first line
echo "CACHE MANIFEST\n";
?>

– Almost everything is done in the function “create_manifest” that iterate 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 caches 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 create 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
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php
function create_manifest($folder) {
  $dir = new RecursiveDirectoryIterator($folder);
  // Iterate through all the files/folders in the current directory
	foreach (new RecursiveIteratorIterator($dir) as $file) {
		$info = pathinfo($file);

		// If the object is a file
		// and it's not called manifest.php (this file),
		// and it's not a dotfile, add it to the list
		if ($file -&gt; IsFile() && $file != "./manifest.php" && substr($file -&gt; getFilename(), 0, 1) != ".") {
			// Replace spaces with %20 or it will break
			echo str_replace(' ', '%20', $file) . "\n";

			// Add this file's hash to the $hashes string
			$hashes .= md5_file($file);
		}
	}
}
?>

– It rest 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
2
3
<?php
create_manifest(".");
?>

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

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

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

And that’s it. Only rest add it into our web page after the doctype declaration:

1
2
>&lt;!DOCTYPE html&gt;
&lt;html manifest="manifest.php"&gt;

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

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