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

发布于 2024-10-08 09:20:43 字数 721 浏览 0 评论 0原文

我正在尝试将 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 显示为字符串。

有什么想法吗?

I am trying to store coldfusion code in a database to be used for the subject of a cfmail. The code stored is as follows:

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

When I retrieve string from the database, I use cfsavecontent to attempt to evaluate it.

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

I also tried

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

And then I replace all the {{ }} with the appropriate values.

However, the subject of the email is stubbornly refusing to contain an evaluated cfif, and is instead showing the cfif as if it were a string.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

︶葆Ⅱㄣ 2024-10-15 09:20:43

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

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

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

作为替代方案,您无需将 CFML 代码存储在数据库中,而是拥有一组存储在服务器上的目录中的 CFML 电子邮件模板文件,并且在数据库中,您只需通过 cfinclude 或 记录需要包含哪个模板cf 模块。

The only way to dynamically evaluate code that you are creating at runtime is via writing it out to a file, and then executing it.

The easiest way would be to write it a .cfm page in the Virtual File System (probably name the file after a UUID, so it's unique), and then it where you need to run the contents.

I wouldn't normally advocate generating code at runtime like this, but it can be the most elegant solution in some cases.

As an alternative, instead of storing the CFML code in the database, you have a set of CFML email template files that get stored in a directory on your server, and in your database you simply record which template needs to be included either via cfinclude or cfmodule.

傲世九天 2024-10-15 09:20:43

您无法动态评估存储在数据库中的 CFML,除非先将其写入文件,然后使用 包含它。

You can't dynamically evaluate CFML stored in a database without first writing it to file and then using <cfinclude> to include it.

囍笑 2024-10-15 09:20:43

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

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

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

Further to Mark's answer here is some psuedo code:

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

I have used code like this before with no problems. Anything in the Virtual File System flies as it is all run in RAM. For best practice do remember to delete the files created ;)

恋竹姑娘 2024-10-15 09:20:43

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

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

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

If you absolutely have to do this, look at the evaluate() function. This, essentially, fires up a new CF thread, compiles the string passed to it, runs it, and returns the result.

If at all possible, I would try to find a way to move your logic to the actual file being run, not the string from the database. I assume you are pulling the data based on some string you've already built, so you might consider appending something to it, so you are looking up subjectDotLegal and subjectDocketLegal or something similar.

Remember, evaluate() is slow, ugly, and can be dangerous (it will run anything passed to it!). If there's a way around it, I suggest you use it.

人生百味 2024-10-15 09:20:43

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

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

它不仅能够做到您希望在脚本中动态添加一些逻辑。我真的建议您查看该项目,甚至可能对其进行改进和贡献。

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

why not just use something like mustache?

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

it has the ability to not only do some of the logic that you want in your script dynamically. i really would suggest you check out the project and maybe even improve and contribute on it.

OH and just for the chance to be on a soapbox: I've been emailing Adobe for years saying that we need the ability to dynamically parse and render CFML. Sadly my cries have only gotten ignored. maybe if more people complained that this feature needs to be added, it would get the attention it deserves.

此岸叶落 2024-10-15 09:20:43

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

下面的代码可以工作:

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

To give an example: Assume code.txt is a text file that contains the following (just to facilitate simulating CFML stored in a db): <cfoutput>#now()#</cfoutput>

The following code would work:

<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" />
风为裳 2024-10-15 09:20:43

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

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

<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 虚拟文件系统,但据我所知,您无法像这样动态创建映射。)

In OpenBlueDragon there is the render function, which can do this.

You can mimic this function in Railo by creating a custom built-in function that saves the file into RAM then cfincludes it, using the following code:

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

(This looks unusual because it needs to allow output, but prevent extra whitespace, hence why all the comments. Unfortunately SO's syntax highlighting seems to be confused by them.)

If you need an ACF-compatible solution, you'll need to use the regular filesystem and a pre-created mapping. (Well, in ACF9 and above you can use the RAM virtual filesystem, but afaik you can't create mappings on the fly like this.)

你另情深 2024-10-15 09:20:43

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

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

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

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

您还可以使用inf cffile 和操作delete 从ram 中删除该文件。

There's a better way, namely using in memory files. This way you don't have any I/O on the disk and therefore much faster:

For tags that take logical path, define mapping in Administrator. Execute in-memory CFM pages using the cfinclude tag:

Create a mapping for ram:/// so that it can be used in the tags. In this example, /inmemory is the mapping that points to ram:///.

For tags that take absolute path, specify the syntax as provided in the following example:

You can also delete the file from the ram usinf cffile and action delete.

半步萧音过轻尘 2024-10-15 09:20:43

以下是我如何存储记录中所有页面的页眉和页脚。该代码可以位于每个页面的顶部。但我把它放在 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>

Here's how I stored my header and footers for all pages in a record. This code can go at the top of each page. But I have it in the APPLICATION.cfm and it seems to be working great.

The key here is not use #pound# signs on your expressions. User [square braces]. The code will pick them and evaluate them and return the result back to the template.

It will substitute the number 0 if it can not evaluate an expression as a means of error handling.

<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>
悸初 2024-10-15 09:20:43

我会尝试内置的 QuoteName 函数

I would try the built-in QuoteName function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文