'auto_reload'=>falsein production with Twig, I need to be able to force a recompilation. The easy way would be to clear the cache directory in the deployer when pushing an update, but if I'm micro-optimizing, why not ship built templates as part of the distribution?
The next obvious question is, "How do I make twig compile templates without rendering them?" and it turns out there's a simple answer. The long form
$twig->loadTemplate("name.twig")->render($vars)is the secret:
loadTemplatewrites to the cache if caching is enabled when the template is loaded.
Conceptually, then, it's dead simple: configure Twig how you normally would, list out all your template files, and call
$twig->loadTemplate()on each of them. I believe the minimal solution on POSIX platforms would look like this:
mkdir -p cache
find templates -name "*.twig" -type f | cut -d/ -f2- | php _build.php
Beautiful! We start out by ensuring the cache directory exists, then find files matching *.twig in the templates directory. Then we pass it through cut, making fields delimited by "/" and taking only the second field and onward. Since find produces names like "templates/user/profile.twig", this strips off the leading "templates/" so that only "user/profile.twig" gets passed to _build.php.
$DS = DIRECTORY_SEPARATOR;
require(__DIR__ . $DS . 'vendor' . $DS . 'autoload.php');
$twig = new Twig_Environment(new Twig_Loader_Filesystem('templates'),
array('cache' => 'cache', 'auto_reload' => true));
while (($fn = fgets(STDIN)))
The job of _build.php is to set up Twig, of course, and then call
loadTemplateon all the filenames that were piped in. (The autoload line assumes Twig was installed via Composer.)
The only downside here is that the list of template directories is written twice: once in the find command, and once in the Twig_Loader_Filesystem constructor. I could easily do all the file manipulation in PHP to take care of that, but it would add more lines of code.