【问题标题】:Groovy's StreamingTemplateEngine throws MissingPropertyException when rendering PHP templateGroovy 的 StreamingTemplateEngine 在渲染 PHP 模板时抛出 MissingPropertyException
【发布时间】:2018-07-16 09:46:05
【问题描述】:

在 Jenkins Pipeline 中,我们部署了一个 PHP 站点,该站点具有 PHP 格式的配置文件。现在我们想使用 StreamingTemplateEngine 来创建这些具有不同内容的配置文件(让我们说用于开发和生产阶段的不同数据库)。 在 PHP 中,变量以 $ - 符号为前缀,现在与来自 StreamingTemplateEngine 的 $ - 符号标记的占位符发生冲突。这意味着它在到达 PHP 变量时会抛出异常,应该保持原样。

我认为一个例子可以更清楚地说明:

模板文件test.php.template:

<?php
$my_php_config_variable = "${StreamingTemplateEnginePlaceholder}"
?>

Groovy 代码片段:

import groovy.text.StreamingTemplateEngine

def placeholders = [
    "StreamingTemplateEnginePlaceholder": "SOME_VALUE",
]
def templateContent = new File('test.php.template').text

def engine = new StreamingTemplateEngine()
def configContent = engine.createTemplate(templateContent).make(placeholders).toString()

println configContent

现在生成的 configContent 字符串应该是:

<?php
$my_php_config_variable = "SOME_VALUE"
?>

但是引擎抛出这个异常:

Exception in thread "main" groovy.text.TemplateExecutionException: Template execution error at line 2:
         1: <?php
     --> 2: $my_php_config_variable = "${StreamingTemplateEnginePlaceholder}"
         3: ?>

    at SimpleGroovyScript.run(SimpleGroovyScript.groovy:10)
    at SimpleGroovyScript.main(SimpleGroovyScript.groovy)
Caused by: groovy.lang.MissingPropertyException: No such property: my_php_config_variable for class: groovy.tmp.templates.StreamingTemplateScript1
    ... 2 more

说,占位符映射中缺少“$my_php_config_variable”。

现在我们的问题是:

1.) 模板中的 PHP 变量能否以某种方式标记为保留给 TemplateEngine 的原样?

或

2.) 引擎能否以某种方式简单地忽略占位符映射中“缺失”的占位符并保持字符串不变?

提前感谢每一个提示! T0mcat

【问题讨论】:

    标签: groovy


    【解决方案1】:

    您必须在模板中转义 $:

    <?php
    \$my_php_config_variable = "${StreamingTemplateEnginePlaceholder}"
    ?>
    

    如果您想使用StreamingTemplateEngine 来呈现此模板,您将不得不稍微更新您的代码。 StreamingTemplateEngine 在渲染输出中留下转义字符,因此您必须在渲染模板中将 \$ 替换为 $:

    import groovy.text.StreamingTemplateEngine
    
    def placeholders = [
      "StreamingTemplateEnginePlaceholder": "SOME_VALUE",
    ]
    def templateContent = new File('test.php.template').text
    
    def engine = new StreamingTemplateEngine()
    def configContent = engine.createTemplate(templateContent)
        .make(placeholders)
        .toString()
        .replaceAll('\\\\\\\$', '\\\$')
    
    println configContent
    

    输出:

    <?php
    $my_php_config_variable = "SOME_VALUE"
    ?>
    

    有一个错误报告GROOVY-8701 记录了这个问题。 Groovy 2.5.x 的未来版本之一应该包含对此的修复,因此不再需要将 \$ 替换为 $。

    您也可以使用GStringTemplateEngine - 在这种情况下不需要替换转义字符:

    import groovy.text.GStringTemplateEngine
    
    def placeholders = [
      "StreamingTemplateEnginePlaceholder": "SOME_VALUE",
    ]
    def templateContent = new File('test.php.template').text
    
    def engine = new GStringTemplateEngine()
    def configContent = engine.createTemplate(templateContent)
        .make(placeholders)
        .toString()
    
    println configContent
    

    输出:

    <?php
    $my_php_config_variable = "SOME_VALUE"
    ?>
    

    【讨论】:

    • 非常感谢您的提示!我已经尝试转义 PHP var 的 $ 符号,但是 - 正如您所提到的 - 最终在呈现的字符串中也转义了 $ 符号。 GString 引擎确实可以按我们的需要工作。在哪种情况下应该更喜欢 StreamingTemplateEngine 而不是 GStringEngine?
    • @T0mcat 检查docs.groovy-lang.org/next/html/documentation/… 以进行 Groovy 模板引擎比较。如果您的模板大于 64K,则应考虑 StreamingTemplateEngine
    • 再次感谢!我会检查一下。
    • 在此处使用StreamingTemplateEngine 处理>64k 的字符串。对于replaceAll,您必须分别删除一个“\”(replaceAll("\\\\\\$", "\\$"))。否则会出现编译错误:Invalid character constant
    猜你喜欢
    • 2012-12-29
    • 2013-07-11
    • 2013-07-24
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多