phpcsshttpcachingauto-versioning

What is an efficient way to cache (auto version) a php file that is created by combining multiple css files?


I have a php file called main.css.php that collects multiple css files and outputs them as one large css file. The number of css files that it collects can range from 1-10. The code is something like this:

header('Content-type: text/css');
header('Cache-Control: max-age=31536000');
ob_start("compress");
function compress($buffer) {
    /* remove comments */
    $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
    /* remove tabs, spaces, newlines, etc. */
    $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer);
    return $buffer;
}

// include css files
foreach ($css_files as $path) {
    if (file_exists($path)) {
        include_once($path);
    }
}
ob_end_flush();

So I have that part sorted but now I'm not sure how to cache it with a way that lets me update the cache if any of the original css files change. As suggested in this answer I was going to do something like:

$cache = "";
foreach ($css_files as $path) {
    $cache.= filemtime($path);
}
...
echo "<link rel='stylesheet' href='/css/base.{$cache}.css'>";

However I can't use this apache rewrite rule:

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]

as I'm not sure how long the $cache will be as it will contain multiple unix timestamps.

Summary

I need to combine multiple css files into one php file that is sent to the browser with a css header. I then needed to correctly cache this file but with a way that allows me to update the cache if any of the original css files change.

Any advice, suggestions, or better ways to go about what I am doing would be much appreciated.


Solution

  • You should make a hash of the $cache variable and use that in the filename. It would be something like this:

    <?php
    
    $cache = "";
    foreach ($css_files as $path) {
        $cache .= filemtime($path);
    }
    
    $cache = md5($cache);
    

    And your rewrite rule would use the length of the hash function; in this case, we use md5, which is 32 characters long:

    RewriteEngine on
    RewriteRule ^(.*)\.[\d]{32}\.(css|js)$ $1.$2 [L]
    

    Hope that helps