【问题标题】:How do I force evaluation of a cfif stored in a string?如何强制评估存储在字符串中的 cfif?
【发布时间】:2013-04-25 09:35:09
【问题描述】:

我正在尝试将冷融合代码存储在数据库中以用于 cfmail 的主题。存储的代码如下:

"RE: <cfif myData.general.legalName NEQ """">  {{dotlegalname}}<cfelse>{{docketLegalName}}</cfif>,    
DOT## {{dot}}, Docket ##(s)   {{docketString}}" 

当我从数据库中检索字符串时,我使用 cfsavecontent 来尝试评估它。

<cfsavecontent variable="subject">
 <cfoutput>#myData.email.subject#</cfoutput>
</cfsavecontent>

我也试过

<cfsavecontent variable="subject">
     <cfoutput>#evaluate(myData.email.subject)#</cfoutput>
</cfsavecontent>

然后我将所有 {{ }} 替换为适当的值。

但是,电子邮件的主题顽固地拒绝包含已评估的 cfif,而是将 cfif 显示为字符串。

有什么想法吗?

【问题讨论】:

    标签: coldfusion if-statement cfmail


    【解决方案1】:

    动态评估您在运行时创建的代码的唯一方法是将其写入文件,然后执行它。

    最简单的方法是将其写入虚拟文件系统中的 .cfm 页面(可能以 UUID 命名文件,因此它是唯一的),然后在您需要运行内容的地方。

    我通常不提倡像这样在运行时生成代码,但在某些情况下它可能是最优雅的解决方案。

    作为替代方案,您可以将一组 CFML 电子邮件模板文件存储在服务器上的目录中,而不是将 CFML 代码存储在数据库中,然后在数据库中记录需要包含的模板通过 cfinclude 或 cfmodule。

    【讨论】:

    • 这不是评估动态代码的唯一方法。但是,模板的想法是一个非常好的想法。
    【解决方案2】:

    如果不先将其写入文件,然后使用&lt;cfinclude&gt; 包含它,则无法动态评估存储在数据库中的 CFML。

    【讨论】:

      【解决方案3】:

      除了马克的回答,这里还有一些伪代码:

      <cfset fileName = createUUID() & ".cfm">
      <cfset fileWrite( fileName, [CODE_FROM_DB]>
      <cfinclude template="#fileName#">
      <cfset fileDelete( fileName )>
      

      我以前使用过这样的代码,没有任何问题。虚拟文件系统中的任何东西都在 RAM 中运行,因此可以飞。为了获得最佳实践,请记住删除创建的文件;)

      【讨论】:

        【解决方案4】:

        如果您绝对必须这样做,请查看 evaluate() 函数。本质上,这会启动一个新的 CF 线程,编译传递给它的字符串,运行它,然后返回结果。

        如果可能的话,我会尝试找到一种方法将您的逻辑移动到正在运行的实际文件,而不是数据库中的字符串。我假设您正在根据已经构建的一些字符串提取数据,因此您可能会考虑在其上附加一些内容,因此您正在查找 subjectDotLegal 和 subjectDocketLegal 或类似的东西。

        请记住,evaluate() 很慢、很丑陋,而且可能很危险(它会运行传递给它的任何东西!)。如果有解决方法,我建议你使用它。

        【讨论】:

        • 其实这不是 100% 正确的。 evaulate() 只会评估一些基本的表达式。例如,您不能将 语句传递给它。它的功能相当有限。
        • 要在评估中使用静态 CF 标签,您只需要使用 DE()(延迟评估)来防止 CF 在评估()运行之前执行标签。与此类似:#evaluate(de("this is truefalse"))#。但是,对于从数据库中传入字符串,您不需要它,因为该字符串不是在编译时定义的。不过,天知道你为什么要评估()一个静态字符串。 :-)
        【解决方案5】:

        为什么不直接使用小胡子之类的东西?

        http://mustache.github.com/ https://github.com/pmcelhaney/Mustache.cfc

        它不仅能够动态地在脚本中执行您想要的一些逻辑。我真的建议你检查一下这个项目,甚至改进它并做出贡献。

        哦,只是为了有机会成为肥皂盒:多年来,我一直在给 Adob​​e 发送电子邮件,说我们需要动态解析和呈现 CFML 的能力。可悲的是,我的哭声只是被忽视了。也许如果更多人抱怨需要添加此功能,它会得到应有的关注。

        【讨论】:

        • 你在ACF bug tracker上提出过吗?如果是这样,请在此处发布 URL。如果没有,请提出实现render(code) 功能的请求,并且 - 如果有足够多的人投票支持 - 希望他们会倾听,并可能将其添加到 CF10。
        • 我会浪费我的呼吸。我已经提交了大约十几次该请求。我已经完成了要求 ACF 实施的事情。我最好复习一下 Java 并在 Railo 中自己实现它。很抱歉,如果这听起来很苛刻,但既然我现在可以自己做,为什么还要多年来乞求 Adob​​e 做某事。
        • 还想提一下,几个月前我将液体模板语言移植到了 Coldfusion。这应该给你两个选择下去。如果你想要一个非常精简、逻辑性强的模板语言,你可以使用 Mustache。如果你需要更强大的东西,你可以使用 Liquid:github.com/rip747/cfml-liquid
        【解决方案6】:

        举个例子:假设code.txt是一个文本文件,包含以下内容(只是为了方便模拟存储在db中的CFML):&lt;cfoutput&gt;#now()#&lt;/cfoutput&gt;

        下面的代码可以工作:

        <cfset q = queryNew("code") />
        <cfset queryAddRow(q,1) />
        <cfset querySetCell(q, "code", fileRead(expandPath('code.txt')), 1) />
        <cfdump var="#q#">
        <cfset newCodeFile = expandPath('dynamic.cfm') />
        <cfset fileWrite(newCodeFile, q.code[1]) />
        <cfinclude template="dynamic.cfm" />
        

        【讨论】:

          【解决方案7】:

          OpenBlueDragon中有render函数,可以做到这一点。

          您可以在 Railo 中模拟此功能,方法是创建一个自定义内置函数,该函数将文件保存到 RAM 中,然后 cfinclude 使用以下代码:

          <cffunction name="render" output="Yes" returntype="string"><!--- 
                 ---><cfargument name="Code" required="Yes" type="string"><!--- 
                 ---><cfset local.mapping = {'/render_ram_resource':'ram://'}><!--- 
                 ---><cfapplication action="update" mappings="#local.mapping#"><!--- 
                 ---><cfset local.fileName = "/render_ram_resource/_render_" & 
          createUUID() & ".cfm"><!--- 
                 ---><cffile action="WRITE" file="#fileName#" 
          output="#arguments.Code#"><!--- 
                 ---><cfinclude template="#fileName#"><!--- 
                 ---><cffile action="DELETE" file="#fileName#"><!--- 
          ---></cffunction> 
          

          (这看起来很不寻常,因为它需要允许输出,但要防止额外的空格,这就是为什么所有 cmets 的原因。不幸的是,SO 的语法突出显示似乎被它们混淆了。)

          如果您需要与 ACF 兼容的解决方案,则需要使用常规文件系统和预先创建的映射。 (好吧,在 ACF9 及更高版本中,您可以使用 RAM 虚拟文件系统,但是您不能像这样动态创建映射。)

          【讨论】:

            【解决方案8】:

            有一个更好的方法,即在内存文件中使用。这样,您的磁盘上就没有任何 I/O,因此速度更快:

            对于采用逻辑路径的标签,在 Administrator 中定义映射。使用 cfinclude 标签执行内存中的 CFM 页面:

            为 ram:/// 创建一个映射,以便在标签中使用它。在本例中,/inmemory 是指向 ram:/// 的映射。

            对于采用绝对路径的标签,请指定以下示例中提供的语法:

            您还可以从 ram usinf cffile 和操作删除中删除文件。

            【讨论】:

              【解决方案9】:

              以下是我在记录中存储所有页面的页眉和页脚的方式。此代码可以放在每一页的顶部。但我在 APPLICATION.cfm 中有它,它似乎工作得很好。

              这里的关键是不要在你的表达中使用#pound# 符号。用户 [方括号]。代码将挑选它们并评估它们并将结果返回给模板。

              如果它不能评估表达式作为错误处理的手段,它将替换数字 0。

              <CFSET FooterID=1234>  <!-- ID of the record you want to use -->
              <CFQUERY NAME="StoredHeader" Datasource="DS1">
                Select Body from templates where id=#FooterID#
              </CFQUERY>
              
              <CFSET Parse=StoredHeader.Body>
              
              <CFLOOP CONDITION="FindNoCase('[',Parse,1) GT 0">
                  <CFSET STB=FindNoCase('[',Parse,1)>
                  <CFSET ENB=FindNoCase(']',Parse,1)>
                  <CFIF ENB-STB GT 0>
                  <CFSET BracketExp=Mid(Parse,STB+1,ENB-1-STB)>
                          <CFTRY>
                              <CFSET BracketValue=Evaluate(BracketExp)>
                              <CFSET Parse=ReplaceNoCase(Parse,'['&BracketExp&']',Evaluate(#BracketExp#))>                
                              <cfcatch type="any">
                                  <div>'Using ZERO 0 for missing <cfoutput>#BracketExp#' </cfoutput> </div>
                                  <CFSET Parse=ReplaceNoCase(Parse,'['&BracketExp&']','0')>
                              </cfcatch>
                          </CFTRY>        
                  </CFIF>
              </CFLOOP>
              <CFSET Footer=Parse>
              
              <cfoutput>FOOTER</cfoutput>
              

              【讨论】:

                【解决方案10】:

                我会尝试内置的QuoteName function

                【讨论】:

                • 问题出在coldfusion端,而不是sql server端,所以我认为你的建议不会有帮助......
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-09-07
                • 1970-01-01
                • 2010-09-27
                • 1970-01-01
                • 2017-12-27
                • 2011-07-02
                • 1970-01-01
                相关资源
                最近更新 更多