在ColdFusion中映射到CFC

13

在我的应用程序中,我将所有的CFC放在一个cfc文件夹中。从网站根目录,我可以通过在我的标签中简单地引用它们来访问它们,如component=cfc.mycomponent method=mymethod

问题是,当我想从另一个不在根目录下的页面访问cfc时,我无法使用component=../.cfc.mycomponent来联系那个cfc。

这里我的做法有什么问题吗?


据我所知,这种相对路径是不被支持的。从该位置开始,你需要使用一个从根目录开始的绝对路径,例如 root.cfc.mycomponent - Leigh
FYI:这是CF搜索组件的方法:http://help.adobe.com/zh_CN/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-7e17.html - Leigh
谢谢Leigh。我在这个特定的网站上使用CF8。我确实注意到指令似乎有些相似。 - Ofeargall
4个回答

26

有几种选项可供实现这个目标。不幸的是,我通过大量的试错才学会了它们。让我分享一下我所学到的。

首先,您可以使用在CF管理器中创建映射的传统方法。指定组件的确切路径(例如c:\wwwroot\cfc),以及您想要使用的映射(伪文件夹)来调用它(例如MyCFCs)。现在,在应用程序的任何地方,您都可以引用new MyCFCs.mycomponent()(使用CF9+的new关键字,您可以替换为createObject("component","MyCFCs.mycomponent")以兼容CF6)。

使用服务器映射的缺点是,您必须在应用程序运行的每个服务器上进行配置。我通常有一个本地开发服务器,其配置与生产服务器截然不同,而在生产服务器上进行更改对我来说很痛苦,因此我尽可能避免使用服务器映射。

其次,您可以使用基于Web根目录的相对路径引用CFC,这意味着如果您的应用程序位于服务器的根目录中,而/cfc路径直接位于Web根目录下,您可以从应用程序的任何地方始终执行new cfc.mycomponent()。ColdFusion 6.1及更高版本将正确映射到您的网站根目录。这就像在任何网站中使用/images/mypicture.jpg引用图像一样,/images会直接进入相同的目录。

使用基于Web根目录的相对路径的缺点是,如果您的应用程序将在Web根目录之外的不同文件夹中,或者有时在子目录中并且有时在Web根目录中,则来自Web根目录的相对路径将发生变化,从而破坏这些链接。

第三,您可以创建一个应用程序特定的映射。这在CF8中引入,并要求您拥有一个Application.cfc文件。添加它很简单。Raymond Camden有一个很好的参考资料。其语法本质上类似于此。

<cfset this.name = "MyAppName"/>
<cfset this.mappings = structNew() />
<cfset this.mappings["/cfc"] = getDirectoryFromPath(getCurrentTemplatePath()) & "cfc/" />
这种方法的唯一缺点是您的Application.cfc无法扩展映射文件夹中的CFC。这是一个不太常见的问题,可能不会影响您。此外,您需要有一个Application.cfc,这是一个好的实践方法,但我不知道您是否已经做到了。
第四步,您可以将CFC实例化为应用程序范围内的对象,可能是在前面提到的Application.cfc内的OnApplicationStart()方法中完成。这将把任何编译/实例化时间移到应用程序的第一次访问中,并从后续的访问中移除它。代码非常简单。
<!--- from Application.cfc, inside onApplicationStart() --->
<cfset application.myComponent = new cfc.myComponent() />

<!--- from anywhere else in your application --->
<cfset application.myComponent.callMyMethod() />
这种方法的缺点是,一旦你的组件在应用内存中,当你开发应用程序时对它所做的任何更改都不会反映出来,除非你清除应用程序内存或再次调用onApplicationStart()。解决起来并不难,但这需要编写更多的代码并进行更多的管理。
最后提醒一句,您可能想考虑从转移到createObject("component",...),或者如果您使用的是CF9,则使用new。cfinvoke语法很好,但每次从路径调用组件时,都会重新实例化它,而且这也不是一种面向对象的调用组件的方式。仅供参考,接受与否取决于您。 :)

4
详细的描述和通俗易懂的解释非常优秀。谢谢。 - Ofeargall
2
只是想回报一下。我已经实现了选项3,它运行得非常好。再次感谢你。 - Ofeargall
我可能太晚了,但是第三个选项可以用来映射其他文件夹吗?比如我的脚本和图像文件夹? - Ofeargall
它适用于服务器端资源,但不适用于客户端文件。您可以通过Web服务器或CF添加虚拟目录,然后构建一个与Web根相关的链接到您的脚本和图像文件夹,并使用它。从您的Application.cfc中,类似这样:<cfset application.imagePath = replace(expandPath("images/"), expandPath("."), "") /> 然后将其引用为 #application.imagePath#/myPhoto.jpg - 我没有测试过,但您可以理解这个想法。 - Nathan Strutz

5
你不能使用相对路径来引用组件。
你需要的是一个 ColdFusion 映射。有两种方法可以实现:
第一种方法是进入 ColdFusion 管理员,进入映射部分并添加一个指向 cfc 文件夹的 /cfc 映射。
另一种方法是使用应用程序专用映射;在你的应用程序的 Application.cfc 中,你可以像在 ColdFusion 管理员映射下那样添加应用程序映射。在你的应用程序 cfc 顶部添加一个 cfset 来设置这个.mappings 数组,并在其中使用目录路径来设置映射。
<cfset this.mappings["/cfc"] = GetDirectoryFromPath( GetCurrentTemplatePath() )&"cfc">

通过将/cfc映射到你的cfc文件夹,任何对cfc.objectname的组件调用将加载你的cfc文件夹中相应的组件。

它必须是 <cfset this.mappings["/cfc"] = ... - 你忘记了 "s"。 - Seybsen

1
你绝对可以使用映射扩展cfc。我自己也不得不这样做。
在ColdFusion中,我最让人沮丧的事情之一是尝试创建一个向公众开放的外部应用程序,并且必须通过子文件夹中的应用程序来保护站点的一部分,并扩展基本application.cfc的逻辑。我将带您了解当前开发人员用于解决此问题的方法,以及如何在可能存在使用虚拟目录的托管提供程序时使用映射。
如果您想跳转到简化的摘要,请滚动到此页面底部。
许多年前,我第一次尝试执行此操作时,无论我尝试什么,都会收到以下消息:“找不到ColdFusion组件或接口xxx”。简而言之,使用此方法的问题是根目录和子文件夹具有相同的名称,即Application.cfc,ColdFusion无法正确识别要扩展的组件。最后,在进行了一些严肃的调查之后,有人想出了在与根Application.cfc相同的根目录中放置代理.cfc的想法,而位于子文件夹中的Application.cfc扩展了一个扩展根cfc的空代理.cfc,如下所示:

根目录: Application.cfc
这个根Application.cfc 没有继承任何东西

同样在根目录下:Proxy.cfc
Proxy.cfc有以下代码,它是基本上为空的唯一 Proxy.cfc 做的事情就是扩展与其在同一目录中的 Application.cfc:

<cfcomponent extends="Application">
</cfcomponent>

子目录 比如一个名为admin的文件夹。
这个子目录里有另一个Application.cfc。假设这个组件负责保护应用程序并具有登录逻辑以及调试设置等功能。 这个Application.cfc 将扩展Proxy.cfc以获取根目录中的Application.cfc的方法和属性,如下所示:

<cfcomponent displayname="Admin" extends="Proxy.cfc">



这种方法是救星,备受推崇。Ben Nadel发布了许多非常有帮助的帖子,我会在本文底部分享。
这很有效,除非你在托管域或使用虚拟目录的服务器上。在这种情况下,我们面临着最初的困境。现在我们回到了“找不到ColdFusion组件或接口xxx”的地狱!
然而,这个棘手问题有一个解决方案,我们需要使用映射!
一种常见的错误认识是,无法使用映射来扩展组件。我不确定这个误解最初是从哪里来的,但事实证明这并不正确。有时候,我们必须使用映射来解决一些恼人的问题,比如这里。
这个网站是由hostek.com托管的。他们是一家很好的公司,但我的网站所在的服务器由于目录结构有些特殊。因此,在使用Proxy.cfc方法将基本Application.cfc中的逻辑扩展到管理文件夹中的Application.cfc时,我遇到了可怕的“找不到…组件”错误。当我第一次看到它时,我感到沮丧,认为不会再出现这种情况了,所以我转向了ColdFusion CFC映射。映射告诉ColdFusion文件在哪里找到以及文件之间的关系。

让我们回顾刚刚讨论的CFC结构。例如,想象以下目录结构:

根目录:即www.gregoryalexander.com/
子目录:www.gregoryalexander.com/admin/

如讨论所述,我们在根目录中有一个Application.cfcProxy.cfc,而在'admin' 子目录中有一个Application.cfc。 Proxy.cfc扩展了位于根目录的Application.cfc,而子目录(admin)中的Application.cfc则扩展了根目录中的Proxy.cfc。

根目录:包含Application.cfc和扩展根Application.cfc的Proxy.cfc。
子目录:Application.cfc(扩展Proxy.cfc)。

现在我们还需要在根Application.cfc中添加以下映射。此映射逻辑应位于根Application.cfc顶部附近,并且不应位于任何Application.cfc事件处理程序(onApplicationStart、onApplicationRequest等)内部。此映射代码除了根Application.cfc外不需要出现在任何其他地方:

<cfset this.mappings = structNew() />
<cfset this.mappings["rootCfc"] = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset this.mappings["adminCfc"] = getDirectoryFromPath( getCurrentTemplatePath() & "/admin" ) />

我使用了 rootCfc 来标识位于根目录中的 Application.cfc,而 adminCfc 则适用于位于 admin 目录中的 Application.cfc。这些变量可以随意命名。请注意,adminCfc 映射的末尾包含字符串 "/admin",该字符串指向 'admin' 子目录。

既然我们在根 Application.cfc 中拥有了这些映射,我们需要将其应用到位于子目录中的 Application.cfc 中的 extends 语句中。在 /admin/Application.cfc 模板中使用:

/admin/Application.cfc
<cfcomponent displayname="xxx" sessionmanagement="xx" clientmanagement="xx" extends="rootCfc.Proxy">

当然,rootCfc 告诉子目录中的 Application.cfc 在根目录中查找 Proxy.cfc 模板。与其他 'extend' 语句一样,在 Proxy 的末尾不需要指定 '.cfc'。

您不需要在根目录下的Proxy.cfc或Application.cfc模板中使用此“extend”映射。它们已经可以相互找到,因为它们都在同一个根目录中。

/Proxy.cfc
<cfcomponent extends="Application"> </cfcomponent>

为了绝对清晰:
根Application.cfc
包含映射逻辑。具有根目录和子目录的映射。
不使用'extend'语句

<cfset this.mappings = structNew() />
<cfset this.mappings["rootCfc"] = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset this.mappings["adminCfc"] = getDirectoryFromPath( getCurrentTemplatePath() & "/admin" ) />

根Proxy.cfm
一个简单的“extends =”Administrator“即可。
没有映射逻辑。

<cfcomponent extends="Application"> </cfcomponent>

子目录 Application.cfc
extends 语句必须是文件夹的映射变量名称(rootCfc),后跟一个点(.)和没有 .cfc 前缀的 Proxy.cfc 模板名称。
<cfcomponent displayname="Admin" sessionmanagement="yes" clientmanagement="yes" extends="rootCfc.Proxy">
非常抱歉我写得这么啰嗦。在解决这个问题时,我感到非常烦恼,但并不像写这篇文章时那么烦恼!
保重!

0

请确保您的组件扩展其他组件时使用完整路径。

例如,一个产品控制器

<cfcomponent displayname="Products" hint="Handles all product requests" extends="core.controller.controller"  output="false">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接