【问题标题】:Symfony2: Twig: Default template file in custom locationSymfony2:Twig:自定义位置的默认模板文件
【发布时间】:2012-10-18 10:16:09
【问题描述】:

我尝试加载一个简单的 base.html.twig 模板文件,该模板文件已从 symfony 的默认位置 app/Resources/views/ 移动到自定义位置 theme/

模板文件包含:

    <!DOCTYPE html>
    <html>
     <head>
     ...
     </head>
     <body>
      {% block body %}{% endblock %}
     </body>
    </html>

控制器Acme\Core\CoreBundle\Controller使用控制器特定模板扩展上述模板文件

    {% extends '::base.html.twig' %}
    {% block body %}
      Hello world!
    {% endblock %}

导致错误提示 Unable to find template "::base.html.twig" in "AcmeCoreCoreBundle:Default:index.html.twig".

如何告诉 symfony 在全局空间中哪里可以找到模板文件?

提前致谢。

【问题讨论】:

  • 可以使用\Twig_Loader_Filesystem::addPath($path, $namespace = '__main__')(参见Source),但不确定从哪里调用它。还查看了 TwigBundle 配置,但看起来那里没有选项。如果有人在这方面进一步扩展,它可能会有所帮助。

标签: php symfony twig


【解决方案1】:

有一个原生功能可以以一种很好的方式完全满足您的需求。本质上,您可以像这样在 app/config.yml 中的 twig 配置中添加一个 twig 命名空间:

twig:
    # ...
    paths:
        "%kernel.root_dir%/../vendor/acme/foo-bar/templates": foo_bar

这将为文件夹 vendor/acme/foo-bar/templates 创建一个别名,然后您可以使用它从控制器中呈现您的模板:

return $this->render(
    '@foo_bar/template.html.twig',
    $data
);

或来自其他树枝模板

{% include '@foo_bar/template.html.twig' %}

来源:官方食谱http://symfony.com/doc/current/cookbook/templating/namespaced_paths.html

【讨论】:

    【解决方案2】:

    由于亚当的暗示,我能够自己回答这个问题。所以如果有人感兴趣,我想提供我的答案。

    AcmeDemoBundle 提供了一个可以简单使用的树枝扩展(Acme\DemoBundle\Twig\Extension\DemoExtension 类)。将构造函数更改为

        public function __construct(FilesystemLoader $loader)
        {
         $this->loader = $loader;
         $this->loader->addPath('path/to/your/directory');
        }
    

    现在告诉 symfony 注册 twig 扩展。编辑您的config.yml 文件(例如app/config/config.yml)并追加

        services:
         demo.twig.extension
          class: Acme\DemoBundle\Twig\Extension\DemoExtension
          tags:
           - { name: twig.extension }
          arguments:
           - @Twig.loader
    

    最后但并非最不重要的一点是更改扩展的树枝文件并从默认模板的命名空间中删除 ::{% extends 'base.html.twig' %}.

    【讨论】:

    • 很高兴我的提示为您指明了正确的方向,感谢您的分享。这个解决方案比我最初考虑提供的解决方案更优雅。
    【解决方案3】:

    我设法找到了另一种实施起来更快的解决方案。我确实首先尝试了这个问题的公认答案,但仍然遇到路径问题。

    就在我的渲染调用模板之前,我将路径添加到 twig.loader 容器,如下所示:

    $this->container->get('twig.loader')->addPath('../../../../theme/', $namespace = '__main__');
    

    现在树枝模板将从根文件夹中名为“主题”的目录呈现。我从 Fabien Pontencier 本人(Symfony 和 Twig 的创建者)那里找到了这个解决方案,在这里回复了一个 twig bug:https://github.com/symfony/symfony/issues/1912

    【讨论】:

    • 正在寻找这个!
    【解决方案4】:

    通过一个操作,您可以从(服务)容器中获取“twig.loader”服务:

    $this->get('twig.loader')->addPath('path/to/your/directory');
    

    然后你就可以在你的模板中使用这个路径了。

    @besta 使用 twig 扩展来实现它,将 twig 加载器注入到构造函数中。但在树枝扩展中,您可以使用环境:

    class YourTwigExtension extends \Twig_Extension {
    ...
       public function initRuntime(\Twig_Environment $environment) {
          $this->environment = $environment;
          $this->environment->getLoader()->addPath(__DIR__ . '/Resources/views');
       }
    ...
    }
    

    【讨论】:

      【解决方案5】:

      假设您希望在全局范围内完成此操作,则此类内容应在 compiler pass 中完成。

      这样会更干净高效:

      <?php
      
      use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
      use Symfony\Component\DependencyInjection\ContainerBuilder;
      
      class CustomCompilerPass implements CompilerPassInterface
      {
          public function process(ContainerBuilder $container)
          {
              $loader = $container->getDefinition('twig.loader');
              $loader->addMethodCall('addPath', array('/path/to/views'));
          }
      }
      

      【讨论】:

      • 这不起作用,它返回'You have requested a non-existent service "twig.loader"。你需要使用'twig.loader.filesystem'
      猜你喜欢
      • 2016-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多