有没有办法在加载任何东西之前显示树枝模板的原始内容?
Is there a way to display the original content of a twig template once it is loaded, before rendering anything?
有人知道是否有办法在加载 twig 模板后在渲染任何内容之前显示它的原始原始内容吗?
假设我有一个根模板:
{# templates/template.txt.twig #}
This is my root template
{{arg1}}
{{ include('other/internal.txt.twig') }}
还有一个从根目录中包含:
{# templates/other/internal.txt.twig #}
This is my included template
{{arg2}}
如果我使用 arg1='foo' 和 arg2='bar' 渲染 template.txt.twig
,结果将是
This is my root template
foo
This is my included template
bar
有没有办法在任何变量评估之前检索加载的模板?
我期望得到这样的东西:
This is my root template
{{arg1}}
This is my included template
{{arg2}}
其背后的想法是利用所有 twig 加载机制(加载路径、命名空间...)
因为我需要对 twig 代码本身进行一些自定义自动检查(与 twig 语法无关,但具有与 twig 无关的高级模型的一致性)
让我知道这是否有意义或者您是否需要更多信息
感谢您的帮助
我相信 Elao/WebProfilerExtraBundle
可在 :
https://github.com/Elao/WebProfilerExtraBundle
可能会为您提供您在上述示例中寻找的其他详细信息。
另请参阅:
http://qpleple.com/webprofilerbundleextra-a-must-have-tool-for-symfony2-developers/
http://www.slideshare.net/matthiasnoback/diving-deep-into-twig
为了呈现模板,Twig 将 Twig 内容编译成 PHP 代码,所以我认为 Twig 本身不可能做到这一点。你可以看看 Thierry 给你的 the doc or at the presentation of Matthias Noback link.
我认为您唯一的解决方案是使用 file_get_contents
读取文件,但您不会像示例中那样在正确的位置包含包含的模板。
如果您想在呈现模板之前使用某种服务处理模板,那么您可以覆盖 twig 环境并运行您在 loadTemplate
方法中进行检查。
例如,我将在每个模板加载时注入 templateValidator
然后 运行。
App\AcmeBundle\Twig\Twig_Environment
首先扩展 \Twig_Environment
并覆盖 loadTemplate
方法并添加一个 setter 用于注入 templateValidator
.
在 loadTemplate
中,我用 $this->validateTemplate($name)
替换了 $this->getLoader()->getSource($name)
的实例,它做同样的事情,但也在你想添加的任何动作之前(在这种情况下 $this->templateValidator->validate($source)
.
namespace App\AcmeBundle\Twig;
use \Twig_Environment as BaseEnvironment;
class Twig_Environment extends BaseEnvironment
{
protected $templateValidator;
public function setTemplateValidator(TemplateValidator $templateValidator)
{
$this->templateValidator = $templateValidator;
}
public function loadTemplate($name, $index = null)
{
$cls = $this->getTemplateClass($name, $index);
if (isset($this->loadedTemplates[$cls])) {
return $this->loadedTemplates[$cls];
}
if (!class_exists($cls, false)) {
if (false === $cache = $this->getCacheFilename($name)) {
//eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
eval('?>'.$this->compileSource($this->validateTemplate($name), $name));
} else {
if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
//$this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
$this->writeCacheFile($cache, $this->compileSource($this->validateTemplate($name), $name));
}
require_once $cache;
}
}
if (!$this->runtimeInitialized) {
$this->initRuntime();
}
return $this->loadedTemplates[$cls] = new $cls($this);
}
/**
* Validate template and return source
*
* @param string $name
* @return string
*/
private function validateTemplate($name)
{
$source = $this->getLoader()->getSource($name);
if (null !== $this->templateValidator) {
$this->templateValidator->validate($source);
}
return $source;
}
}
app/config/config.yml
重写参数 twig.class
所以 DI 使用你的 class 而不是原来的 \Twig_Environment
.
parameters:
twig.class: App\AcmeBundle\Twig\Twig_Environment
App\AcmeBundle\DependencyInject\Compiler\TwigEnvironmentInjectCompilerPass
创建一个编译器 class 以将 templateValidator
注入到您新创建的 TwigEnvironment
中(只有当它具有 'setTemplateValidator'
方法时才能正确降级)
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
class TwigEnvironmentInjectCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('twig') ||
!$container->hasDefinition('acme.template_validator'))
{
return;
}
$twig = $container->getDefinition('twig');
if (!$twig->hasMethodCall('setTemplateValidator')) {
return;
}
$twig->addMethodCall(
'setTemplateValidator',
array(new Reference('acme.template_validator'))
);
}
}
App\AcmeBundle\AppAcmeBundle
将您的编译器传递添加到包构建
use App\AcmeBundle\DependencyInject\Compiler\TwigEnvironmentInjectCompilerPass;
class AppAcmeBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new TwigEnvironmentInjectCompilerPass());
}
}
注意这没有经过任何测试,它只是我的头脑,所以它可能都是错误的。
有人知道是否有办法在加载 twig 模板后在渲染任何内容之前显示它的原始原始内容吗?
假设我有一个根模板:
{# templates/template.txt.twig #}
This is my root template
{{arg1}}
{{ include('other/internal.txt.twig') }}
还有一个从根目录中包含:
{# templates/other/internal.txt.twig #}
This is my included template
{{arg2}}
如果我使用 arg1='foo' 和 arg2='bar' 渲染 template.txt.twig
,结果将是
This is my root template
foo
This is my included template
bar
有没有办法在任何变量评估之前检索加载的模板? 我期望得到这样的东西:
This is my root template
{{arg1}}
This is my included template
{{arg2}}
其背后的想法是利用所有 twig 加载机制(加载路径、命名空间...) 因为我需要对 twig 代码本身进行一些自定义自动检查(与 twig 语法无关,但具有与 twig 无关的高级模型的一致性)
让我知道这是否有意义或者您是否需要更多信息 感谢您的帮助
我相信 Elao/WebProfilerExtraBundle
可在 :
https://github.com/Elao/WebProfilerExtraBundle
可能会为您提供您在上述示例中寻找的其他详细信息。
另请参阅:
http://qpleple.com/webprofilerbundleextra-a-must-have-tool-for-symfony2-developers/
http://www.slideshare.net/matthiasnoback/diving-deep-into-twig
为了呈现模板,Twig 将 Twig 内容编译成 PHP 代码,所以我认为 Twig 本身不可能做到这一点。你可以看看 Thierry 给你的 the doc or at the presentation of Matthias Noback link.
我认为您唯一的解决方案是使用 file_get_contents
读取文件,但您不会像示例中那样在正确的位置包含包含的模板。
如果您想在呈现模板之前使用某种服务处理模板,那么您可以覆盖 twig 环境并运行您在 loadTemplate
方法中进行检查。
例如,我将在每个模板加载时注入 templateValidator
然后 运行。
App\AcmeBundle\Twig\Twig_Environment
首先扩展 \Twig_Environment
并覆盖 loadTemplate
方法并添加一个 setter 用于注入 templateValidator
.
在 loadTemplate
中,我用 $this->validateTemplate($name)
替换了 $this->getLoader()->getSource($name)
的实例,它做同样的事情,但也在你想添加的任何动作之前(在这种情况下 $this->templateValidator->validate($source)
.
namespace App\AcmeBundle\Twig;
use \Twig_Environment as BaseEnvironment;
class Twig_Environment extends BaseEnvironment
{
protected $templateValidator;
public function setTemplateValidator(TemplateValidator $templateValidator)
{
$this->templateValidator = $templateValidator;
}
public function loadTemplate($name, $index = null)
{
$cls = $this->getTemplateClass($name, $index);
if (isset($this->loadedTemplates[$cls])) {
return $this->loadedTemplates[$cls];
}
if (!class_exists($cls, false)) {
if (false === $cache = $this->getCacheFilename($name)) {
//eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
eval('?>'.$this->compileSource($this->validateTemplate($name), $name));
} else {
if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
//$this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
$this->writeCacheFile($cache, $this->compileSource($this->validateTemplate($name), $name));
}
require_once $cache;
}
}
if (!$this->runtimeInitialized) {
$this->initRuntime();
}
return $this->loadedTemplates[$cls] = new $cls($this);
}
/**
* Validate template and return source
*
* @param string $name
* @return string
*/
private function validateTemplate($name)
{
$source = $this->getLoader()->getSource($name);
if (null !== $this->templateValidator) {
$this->templateValidator->validate($source);
}
return $source;
}
}
app/config/config.yml
重写参数 twig.class
所以 DI 使用你的 class 而不是原来的 \Twig_Environment
.
parameters:
twig.class: App\AcmeBundle\Twig\Twig_Environment
App\AcmeBundle\DependencyInject\Compiler\TwigEnvironmentInjectCompilerPass
创建一个编译器 class 以将 templateValidator
注入到您新创建的 TwigEnvironment
中(只有当它具有 'setTemplateValidator'
方法时才能正确降级)
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
class TwigEnvironmentInjectCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('twig') ||
!$container->hasDefinition('acme.template_validator'))
{
return;
}
$twig = $container->getDefinition('twig');
if (!$twig->hasMethodCall('setTemplateValidator')) {
return;
}
$twig->addMethodCall(
'setTemplateValidator',
array(new Reference('acme.template_validator'))
);
}
}
App\AcmeBundle\AppAcmeBundle
将您的编译器传递添加到包构建
use App\AcmeBundle\DependencyInject\Compiler\TwigEnvironmentInjectCompilerPass;
class AppAcmeBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new TwigEnvironmentInjectCompilerPass());
}
}
注意这没有经过任何测试,它只是我的头脑,所以它可能都是错误的。