Question

I wrote custom Twig loader that fetch templates from database and it works in Twig "standalone" library. Now i want to use that in Symfony2 but can't find where to change Twig loader via Symfony2 settings.

Thx in advance for any tips on that

Was it helpful?

Solution

Have a look at this page at GitHub. Specially <parameter key="twig.loader.class">Symfony\Bundle\TwigBundle\Loader\Loader</parameter>

You can configure this key in your config.yml

OTHER TIPS

Register your own twig loader + tell Twig_Loader_Chain to try loading with your loader at first. You can create and add as many loaders to your Twig_Loader_Chain as you want.

services:
    Acme.corebundle.twig.loader.filesystem:
        class: Acme\CoreBundle\Twig\Loader\Filesystem
        tags:
            - { name: templating.loader }

    Acme.corebundle.twig_chain_loader:
        class: Twig_Loader_Chain
        calls:
            - [ addLoader, [@Acme.corebundle.twig.loader.filesystem] ]
            - [ addLoader, [@twig.loader] ]

Now you should create your loader. Twig loaders have to implement Twig_LoaderInterface.

Acme/CoreBundle/Twig/Loader/Filesystem.php

PSEUDOCODE:

namespace Acme\CoreBundle\Twig\Loader;

use Twig_LoaderInterface;


class Filesystem implements Twig_LoaderInterface {

    /**
     * {@inheritdoc}
     */
    public function getSource($name)
    {
        //code...
    }

    /**
     * {@inheritdoc}
     */
    protected function findTemplate($name)
    {
        //code...
    }

    /**
     * {@inheritdoc}
     */
    public function isFresh($template, $time)
    {
        //code...
    }

    //...
}

Now we have defined our services and created a new loader. Problem is that Twig doesn't know about our new Twig_Loader and still uses its own -default- "twig.loader".

To check run on CLI:

app/console container:debug twig.loader

In order to modify services outside of your own bundle you have to use CompilerPasses. Create our own that assigns your loader service to the twig environment:

Acme/CoreBundle/DependencyInjection/Compiler/TwigFileLoaderPass.php

<?php

namespace Acme\CoreBundle\DependencyInjection\Compiler;

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

class TwigFileLoaderPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $definition = $container->getDefinition('twig');
        $definition->addMethodCall('setLoader', array(new Reference('Acme.corebundle.twig_chain_loader')));
    }
}

There is the "addMethodCall" call which does nothing more than defining a setter injection as in the service definitions. The difference is that in a compiler pass you can access every service, not only your own ones. As you can see the chain loader has been defined as the new loader for the twig environment.

To Accomplish this task you have to tell Symfony that it should use this compiler pass. Compiler passes can be added in your bundle class:

Acme/CoreBundle/AcmeCoreBundle.php

<?php

namespace Acme\CoreBundle;

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

use Acme\CoreBundle\DependencyInjection\Compiler\TwigFileLoaderPass;

class AcmeCoreBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $container->addCompilerPass(new TwigFileLoaderPass());
    }
}

If the corresponding file does not exist your new Twig_Loader_Filesystem throws an error and the chain loader continues with default twig loader as fallback.

To overwrite the key in your config.yml you need to do it under services not twig as it's not support in the configuration parser at the moment (2.0.9)

twig:
    cache:...
    debug:...
    ...

services:
        twig.loader:
            class: Acme\CoreBundle\Twig\Loader\FilesystemLoader
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top