How to change Twig loader via Symfony2 settings
I wrote custom Twig loader tha开发者_如何学编程t 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
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.
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
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
精彩评论