Compile a referenced LESS file into CSS with PHP automatically

caching, compiler-construction, css, less, php

Solution

THIS ASSUMES LESSPHP v0.3.8+ Unsure about earlier versions, but you'll get the gist of how it works if it doesn't straight out of the box.

`<link rel="stylesheet" type="text/css" href="styles/main.less" />`

If you were using less.js to compile client side, make sure you change `rel="stylesheet/less"` to `rel="stylesheet"`

1) Grab Lessphp I placed these files in `/www/compilers/lessphp/` for the context of this demo

2) Make a PHP script that we can throw out LESS files at. This will deal with caching, compiling to CSS and returning the CSS as a response. I have placed this file at `/www/compilers/` and called it `lessphp.php`

Most of this code was on the Lessphp site, except there were errors in it, and I have added the response at the end.

<?php
require "lessphp/lessc.inc.php";
$file = $_GET["file"];
function autoCompileLess($inputFile, $outputFile) {
    // load the cache
    $cacheFile = $inputFile.".cache";
    if (file_exists($cacheFile)) {
        $cache = unserialize(file_get_contents($cacheFile));
    } else {
        $cache = $inputFile;
    }
    $less = new lessc;
    $less->setFormatter("compressed");
    $newCache = $less->cachedCompile($cache);
    if (!is_array($cache) || $newCache["updated"] > $cache["updated"]) {
        file_put_contents($cacheFile, serialize($newCache));
        file_put_contents($outputFile, $newCache['compiled']);
    }
}
autoCompileLess('../' . $file, '../' . $file . '.css');
header('Content-type: text/css');
readfile('../' . $file . '.css');
?>

This will compile the LESS file (eg, `styles/main.less`) to a cache file and a CSS file (eg, `styles/main.less.css`).

3) Add a `mod_rewrite` rule so that any LESS files a user requests are redirected to our compiler, giving it its path. This was placed in the root `.htaccess` file.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^([^.]*\.less)$ compilers/lessphp.php?file=$1 [R,QSA,L]
</ifModule>

If you are using WordPress, this rule will need to come after it - even if WordPress is in a sub directory, it seems to overwrite these rules, and LESS compilation will not occur for referenced files which exist below (directory wise) WordPress's `.htaccess` rules.

4) Your LESS code should be relatively referenced in relation to the compilers location. Additionally, Lessphp compiler will fail if there are empty attributes, eg. `background-color: ;`

If all is working well, the following should occur:

Directly browse your LESS file `http://domain.com/styles/main.less`

Be automatically redirected to `http://domain.com/compilers/lessphp?file=styles/main.less`

Be presented with minified CSS

`main.less.css` and `main.less.cache` should now exist in the same directory as your LESS file

The last modified dates shouldn’t change unless you update your LESS file

Problem

I want the following things to occur: Have the process automated server side. Simply be able to reference the LESS file as I would a CSS file in my code. The user is returned minified CSS instead of the LESS file - cached so the compiler doesn't need to run unless the LESS file has been updated. For this to work with any LESS file that is referenced anywhere within my domain. I spotted Lessphp, but the documentation isn't very clear, nor does it explain how to dynamically get any LESS file to it. I thought I would post up how I got it all working as I haven't seen a run through on how to achieve this with PHP.

Original source