我正在尝试将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显示为字符串。
有什么想法吗?
答案 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。