Loading Twig templates from an additional directory

posted 25.08.2014

The standard Twig loader in a Symfony app loads templates from the app/ directory and from Bundle resources. To load them from an additional location, it is possible to add a custom loader.

Since Twig uses a single loader, Twig_Loader_Chain is used to wrap the original loader and the new custom loader. The original loader is registered in the container as twig.loader, the custom loader will be a configured instance of Twig_Loader_Filesystem. The following configuration puts it altogether.

symfony_blog.twig.loader.custom:
    class: Twig_Loader_Filesystem
    arguments: [ %custom_template_path% ]
    tags:
        - { name: templating.loader }

symfony_blog.twig.loader.chain:
    class: Twig_Loader_Chain
    calls:
        - [ addLoader, [@symfony_blog.twig.loader.custom] ]
        - [ addLoader, [@twig.loader] ]

Next, we need to set our chain loader in Twig. This is not possible in YAML, a compiler pass is needed.

<?php

use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

class CustomLoaderPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $definition = $container->getDefinition('twig');
        $definition->addMethodCall('setLoader', [new Reference('symfony_blog.twig.loader.custom')]);
    }
}

To register the compiler pass, we simply add it in the Bundle class.

<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class ExampleBundle extends Bundle
{

    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $container->addCompilerPass(new CustomLoaderPass());
    }

}