如何在Symfony2/Twig模板中包含原始的HTML文件?

10

我正在Symfony2项目中工作,有几个小的HTML部分需要包含在我的主视图中。根据官方Twig文档,我应该能够简单地使用{% include 'filename.html' %},但是在Symfony中,除非文件名以“.html.twig”结尾,否则会抛出错误,表示找不到文件。我想避免为这些文件使用Twig模板,因为它们没有动态内容并且有很多双大括号(它们是JavaScript模板)。要求模板设计者将每个这样的文件都包装在{% raw %}标签中似乎是一种非常笨拙的方法。


如果官方文档说应该可以工作,那么也许你应该尝试更新Twig和Twig Bundle到新版本(编辑你的deps文件)。 - greg0ire
我已经尝试过了,但我认为这个问题与Twig无关,而是与Symfony处理模板位置/类型的方式有关。 - wdh
那你或许应该提交一个错误报告。 - greg0ire
4个回答

10

我也遇到了同样的问题,尝试找到一种解决方案,将包含文件(mustache模板)作为原始内容包含在Twig模板中,以便Twig不会尝试解析它们。

起初,我把我的mustache模板文件命名为简单的sometemplate.html,并用{% raw %}标签包装起来。这段时间内运行良好,但后来我开始使用带有Handlebars插件的PhpStorm IDE(用于mustache语法)。为了让 PhpStorm 认识到文件是mustache语法,它们需要有唯一的文件扩展名(默认情况下是.mustache),因此我将我的 sometemplate.html 重命名为 sometemplate.mustache,但我真的不喜欢我的mustache模板需要用Twig标签包装。所以最终我采用了@rdjs 在他的第三个选项中提到的做法。我认为这是最好的解决方案。

以下是我制作的可工作的 Twig 扩展函数:

function twig_include_raw(Twig_Environment $env, $template) {
    return $env->getLoader()->getSource($template);
}
$twig->addFunction('include_raw', new Twig_Function_Function('twig_include_raw', array('needs_environment' => true)));

有了这个设置,您可以轻松地将文件作为“原始”文件包含,而无需通过Twig解析它们,方法如下:

{{ include_raw('sometemplate.mustache')|raw }}

我甚至制作了一个Twig宏来简化将mustache模板包含到HTML head部分的过程:

{% macro mustache_script(id, file) -%}
<script id="{{ id }}" type="text/x-mustache-template">
{{ include_raw(file)|raw }}
</script>
{%- endmacro %}

将上述宏定义导入到您的Twig模板中(例如{% import "macros.twig" %}),然后您可以在Twig模板中轻松地导入mustache模板文件,只需在HTML <head>部分内输入{{ mustache_script('sometemplate_tpl', 'sometemplate.mustache') }}即可。

我希望这能帮助正在寻找相同问题解决方案的人。


这似乎可以解决我正在研究的问题,但我不知道twig_include_raw函数应该在哪里定义以及什么时候/何时调用$twig->addFunction。您能否进一步解释一下? - Craig
@Craig 抱歉我没有早点回复你。你可以在任何地方定义函数。只需确保在使用 $twig = new Twig_Environment($loader); 设置 Twig 后的任何位置调用 $twig->addFunction() 即可。我通常有自己的 twigInit() 函数,它处理设置 Twig 环境,包括加载我使用的扩展。您可能还想阅读有关扩展 Twig 的文档页面,网址为 http://twig.sensiolabs.org/doc/advanced.html - Haprog
2
太好了。如果在needs_environment后的选项中添加'is_safe'=> array('all'),则可以绕过对“| raw”的需求。 - Matt Kenefick
你从哪个命名空间“使用”Twig_Function_Function?这段代码在哪里添加?我正在尝试在控制器中添加。编辑:啊,new \Twig_Function_Function - user1850421

8
快速回顾twig文件扩展名(摘自文档):
每个模板名称都有两个扩展名,用于指定该模板的格式和引擎。
AcmeBlogBundle:Blog:index.html.twig - HTML format, Twig engine
AcmeBlogBundle:Blog:index.html.php - HTML format, PHP engine
AcmeBlogBundle:Blog:index.css.twig - CSS format, Twig engine

默认情况下,Symfony2模板可以使用Twig或PHP编写,扩展名的最后一部分(例如.twig或.php)指定应使用这两个引擎中的哪一个。扩展名的第一部分(例如.html、.css等)是模板将生成的最终格式。
因此,即使不会出现错误,将文件包含为.html也至少会产生歧义。
因此,您有3个选择:
1. 如果文件纯粹是JavaScript,则在页面中包含它们作为脚本标记。 2. 如果它们是混合的HTML和JS,则使用{% raw %}转义JS,并将文件包含为foo.html.twig模板。如果像这样包含了许多脚本,则大多数情况下您的设计师可能需要进行一些重构,并将其大部分脚本移动到外部文件中(请参见选项1)。 3. 如果您确实坚持要这样做,您可以编写Twig扩展来包含原始HTML文件。(编辑:有关此选项的更多详细信息,请参见@Haprog的答案)。 {{ include_html('foo/bar.html') }} 4. 更新2015年,twig已经添加了source函数: {{ source('AcmeSomeBundle:Default:somefile.html.twig') }}
向下面的评论中的@Nigel Angel致敬,提供了第4个选项。

1
我想做的是为Mustache模板提供一种在页面中包含它们以供JavaScript使用的方法。将它们直接放在模板中并用{% raw %}标签包围起来可以工作,但我觉得这样很杂乱,并且当有很多小模板片段时会变得难以控制。通过ajax加载模板片段会不必要地减慢客户端的速度,因为会有更多的请求。将模板放在一个没有实际twig标记的twig文件中(除了{% raw %})会让我这个强迫症开发者感到困扰,但在这种情况下似乎是最简单的选择。谢谢。 - wdh
5
Twig自那时起已添加了source函数{{ source('AcmeSomeBundle:Default:somefile.html.twig') }}。 - user1850421
能否使用 phtml 文件代替? - Yes Barry

6

3
如果您使用电话分机,请按照以下方式申请延期,跟进Kari的事项。
public function getFunctions() {
    return [
        'include_raw' =>  new \Twig_Function_Method($this, 'twig_include_raw', array('needs_environment'=> true, 'is_safe'=> array('all')))
    ];
}

这将需要使用 $this->twig_include_raw 类型的方法。您可以在模板中包含如下:

{{ include_raw("my/file/here.html.twig") }}

不需要使用“| raw”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接