如何强制评估存储在字符串中的cfif?

时间:2010-12-20 21:31:51

标签: coldfusion if-statement cfmail

我正在尝试将coldfusion代码存储在数据库中以用于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显示为字符串。

有什么想法吗?

10 个答案:

答案 0 :(得分:3)

如果没有先将文件写入文件,然后使用<cfinclude>将其包含在内,则无法动态评估存储在数据库中的CFML。

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:2)

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

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

请记住,evaluate()是缓慢的,丑陋的,并且可能是危险的(它将运行传递给它的任何!)。如果有办法,我建议你使用它。

答案 3 :(得分:2)

此外,Mark的回答是一些伪代码:

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

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

答案 4 :(得分:2)

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

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

它不仅可以动态地在脚本中执行您想要的某些逻辑。我真的建议你查看项目,甚至可以改进并做出贡献。

OH,只是为了有机会使用肥皂盒:我多年来一直在向Adobe发送电子邮件说我们需要能够动态解析和渲染CFML。可悲的是,我的哭声只是被忽略了。也许如果有更多的人抱怨需要添加这个功能,它会得到应有的关注。

答案 5 :(得分:0)

举个例子:假设code.txt是一个包含以下内容的文本文件(只是为了便于模拟存储在数据库中的CFML):<cfoutput>#now()#</cfoutput>

以下代码可行:

<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" />

答案 6 :(得分:0)

OpenBlueDragon中有render功能,可以执行此操作。

您可以通过创建自定义内置函数来模拟Railo中的此函数,该函数将文件保存到RAM中,然后使用以下代码将其包括在内:

<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> 

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

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

答案 7 :(得分:0)

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

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

为ram:///创建一个映射,以便可以在标记中使用它。在此示例中,/ inmemory是指向ram:///。

的映射

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

您也可以从ram usinf cffile和action delete中删除该文件。

答案 8 :(得分:0)

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

这里的关键是不要在你的表情上使用#pound #sign。用户[方括号]。代码将选择它们并对它们进行评估并将结果返回给模板。

如果无法将表达式计算为错误处理方法,它将替换数字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>

答案 9 :(得分:-1)

我会尝试内置的QuoteName function