映射到 ColdFusion 中的 CFC
在我的应用程序中,我将所有 CFC 都放在 cfc 文件夹中。从站点根目录,我可以轻松地访问它们,只需在我的
标记中将它们引用为 component=cfc.mycomponent method=mymethod
问题是,当我想从不在根目录中的另一个页面访问 cfc 时,我无法使用 component=../.cfc.mycomponent
来联系该 cfc。
我在这里做错了什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
有多种选择可以使其发挥作用。不幸的是,学习它们让我经历了大量的尝试和错误。让我分享一下我学到的东西。
首先,您可以使用在 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 的相对路径root 将会改变,从而破坏这些链接。
第三,您可以创建特定于应用程序的映射。这是在 CF8 中引入的,要求您有一个
Application.cfc
文件。添加起来很简单。 Raymond Camden 有很棒的参考。语法本质上是这样的。此方法的唯一缺点是您的 Application.cfc 无法扩展映射文件夹中的 CFC。这是一个不起眼的问题,可能不会影响您。另外,您需要有一个 Application.cfc,这是一个很好的做法,但我不知道您是否正在这样做。
第四,您可以将 CFC 实例化到应用程序范围中,可能是在前面提到的 Application.cfc 中的
OnApplicationStart()
方法内。这会将所有编译/实例化时间移至应用程序的第一次命中,并将其从后续命中中删除。代码非常简单。这样做的缺点是,一旦您的组件位于应用程序内存中,您在开发应用程序时对其所做的任何更改都不会反映出来,直到您清除应用程序内存或再次调用 onApplicationStart() 为止。这并不难解决,但只是需要更多代码,并且需要管理更多。
最后一点,您可能需要考虑从
迁移到createObject("component",...)
或者,如果您使用的是 CF9,新
。 cfinvoke 语法很好,但每次从路径调用组件时,都会重新实例化它,而且它也不是一种非常面向对象的调用组件的方式。深思熟虑,要么接受要么放弃:)There are a handful of options for getting this to work. Unfortunately, learning them has taken me a good amount of trial and error. Let me share what I've learned.
First, you can use the classic method of creating a mapping in your CF Administrator. Specify the exact path to your components (e.g.
c:\wwwroot\cfc
), and the mapping (pseudo-folder) that you want to call it by (e.g.MyCFCs
). Now from anywhere in your application, you can reference create anew MyCFCs.mycomponent()
(using CF9+'snew
keyword, you can substitute for createObject("component","MyCFCs.mycomponent") to be compatible back to CF6).The downsides to using a server mapping are that you have to configure this on every server your application runs on. I typically have a local development server which has a radically different configuration from my production servers, and making changes on production servers is a pain for me, so I try to avoid server mappings whenever possible.
Second, you can reference your CFCs from a web-root-relative path, meaning that if your application is in the root of your server and the
/cfc
path is directly off of the web root, you can always donew cfc.mycomponent()
from anywhere in your application. ColdFusion 6.1 and up will correctly map to the root of your web site. This is like referencing an image using/images/mypicture.jpg
, anywhere in your web site,/images
will will go straight to the same directory.The downside of using the web-root-relative path is that if your application will ever be in a different folder off of the web root, or will ever be in a subdirectory and sometimes be at the web root, the relative path from the web root will change, breaking these links.
Third, you can create an application-specific mapping. This was introduced in CF8 and requires that you have an
Application.cfc
file. It is simple to add. Raymond Camden has a great reference. The syntax is essentially like this.The only downside to this method is that your Application.cfc can't extend a CFC in a mapped folder. It's an obscure problem, which probably won't affect you. Also, you will need to have an Application.cfc, which is good practice, but I don't know if you are doing that yet.
Fourth, you can instantiate your CFC into your application scope, probably from within the aforementioned Application.cfc, inside an
OnApplicationStart()
method. This moves any compile/instantiation time into your application's first hit, and removes it from subsequent hits. The code is very simple.The downside to this one is that once your component is in Application memory, any changes you make to it while you are developing your application will not be reflected until you clear the application memory or call onApplicationStart() again. It's not hard to get around, but it's just more code, and more to manage.
One final note, you may want to think about moving from
<cfinvoke>
tocreateObject("component",...)
or, if you are on CF9,new
. The cfinvoke syntax is fine, but every time you invoke a component from a path, you are re-instantiating it, and it also is not a very object-oriented way to call your components. Food for thought, take it or leave it :)您不能对组件使用相对路径。
您需要的是 ColdFusion 映射。有两种方法可以做到这一点。
第一种方法是进入 ColdFusion 管理员,进入映射部分并添加指向您的 cfc 文件夹的 /cfc 映射。
另一种方法是使用特定于应用程序的映射;
在应用程序的 Application.cfc 中,您可以添加应用程序映射,就像在 ColdFusion 管理员映射下一样。在应用程序 cfc 的顶部添加 this.mappings 的 cfset 作为数组。在此数组中设置与目录路径的映射。
通过将 /cfc 映射到您的 cfc 文件夹,任何对 cfc.objectname 的组件调用都将在您的 cfc 文件夹中加载相应的组件。
You can't use relative paths with components.
What you need is a ColdFusion mapping. There are two ways to do this.
The first is to go into your ColdFusion administrator, go into the mappings section and add a /cfc mapping that points to your cfc folder.
The other way is to use application specific mappings;
In the Application.cfc for your application you can add application mappings as you would under the ColdFusion administrator mapping. At the top of your application cfc add a cfset of this.mappings as an array. In this array set the mapping with the directory path.
with the mapping of /cfc to your cfc folder any component calls to cfc.objectname will load the appropriate component in your cfc folder.
您绝对可以使用映射来扩展 cfc。我必须自己做。
我在 ColdFusion 中必须处理的最令人沮丧的事情之一是尝试创建一个向公众开放的外部应用程序,并且必须使用子文件夹中的应用程序来保护该站点的一部分,并从基础扩展逻辑应用程序.cfc。我将引导您了解开发人员用于解决此问题的当前方法,并向您展示当可能存在使用虚拟目录的托管提供商时如何另外使用映射。
这是一篇相当长的文章,如果您想跳到摘要,请向下滚动到本页底部。
许多年前,我第一次尝试执行此操作时,无论我尝试什么,我都会收到以下消息:“无法找到 ColdFusion 组件或接口 xxx”。简而言之,问题是使用这种方法的缺点是根文件夹和子文件夹都具有相同的名称,即Application.cfc,并且ColdFusion无法正确识别要扩展的组件。最后,经过一番认真的调查,有人提出了创建代理的想法。 .cfc 驻留在与根 Application.cfc 相同的根目录,并且子文件夹中的 Application.cfc 扩展了一个空 proxy.cfc,该代理.cfc 扩展了根 cfc,如下所示:
根目录:Application.cfc
此根 Application.cfc 不扩展任何内容
也在根目录中:Proxy.cfc
Proxy.cfc 有以下代码,它本质上是空的。 Proxy.cfc 所做的唯一事情是扩展同一目录中的 Application.cfc:
子目录,例如名为 admin 的文件夹。
该子目录还有另一个 Application.cfc。假设该组件负责保护应用程序并具有登录逻辑以及调试设置等。 此Application.cfc将扩展Proxy.cfc以获取根目录中Application.cfc的方法和属性,如下所示:
这种方法是天赐之物,并且在博客中得到了广泛的关注。 Ben Nadel 发表了许多非常有用的帖子,我将在本文底部分享这些帖子。
除非您位于托管域或使用虚拟目录的服务器上,否则这种方法效果很好。在这种情况下,我们就处于我们出发时的同一条船上。现在我们又回到了“找不到 ColdFusion 组件或接口 xxx' 地狱!
虽然这个棘手的问题有一个解决方案,但我们还需要使用映射!
不能使用映射来扩展组件是一个常见的误用词,我不太确定这种误解最初是从哪里产生的,但事实证明这是不正确的,在某些情况下我们必须<。 /b> 使用映射来解决一些烦人的问题问题,就像这里一样。
这个特定的网站由 hostek.com 托管。他们是一家很好的公司。处理,但是由于目录结构,我的网站托管的服务器有一些特性。在这里,当我使用 Proxy.cfc 方法将逻辑从基础 Application.cfc 扩展到 Application.cfc 时。在管理文件夹中我收到当我第一次看到它时,我很沮丧地想到了“无法找到...组件”错误,因此我转向 ColdFusion CFC 映射。映射告诉 ColdFusion 在哪里可以找到文件以及文件关系是什么。
让我们回顾一下刚才讨论的 CFC 结构。例如,想象一下以下目录结构:
根目录:即www.gregoryalexander.com/< br>
子目录: www.gregoryalexander.com/admin/
正如所讨论的,我们有一个根目录中的>Application.cfc和Proxy.cfc,并且我们在'admin'目录中有Application.cfc ' 子目录。
Proxy.cfc 扩展了根目录中的Application.cfc,子目录(admin) 中的Application.cfc 扩展了根目录中的Proxy.cfc。
根目录:包含 Application.cfc 和 Proxy.cfc(扩展根 Application.cfc)。
子目录:Application.cfc(扩展 Proxy.cfc)。
现在我们还需要在根 Application.cfc 中添加以下映射。此映射逻辑应位于根 Application.cfc 的顶部附近,并且不应位于任何 Application.cfc 事件处理程序(onApplicationStart、onApplicationRequest 等)内。此映射代码不需要位于根 Application.cfc 之外的任何位置:
我使用rootCfc来识别根目录中的Application.cfc,而adminCfc适用于Application在管理目录中。这些变量可以命名为任何名称。请注意,adminCfc 映射末尾的“/admin”字符串指向“admin”文件夹,它是一个子目录。
现在我们在根 Application.cfc 中拥有了映射,我们需要将它们应用到位于子目录中的 Application.cfc 中的 extends 语句。在 /admin/Application.cfc 模板中使用:
/admin/Application.cfc
当然,rootCfc告诉子目录中的Application.cfc去根目录中寻找Proxy.cfc模板。与其他“extend”语句一样,您不需要在 Proxy 末尾指定“.cfc”。
您不需要在根 Proxy.cfc 或 Application.cfc 模板中使用此“扩展”映射。他们已经可以找到对方,因为它们都位于同一根目录中。
/Proxy.cfc
Summary
为了绝对清楚起见:
根Application.cfc
包含映射逻辑。具有根目录和子目录的映射。
不使用“extend”语句
根Proxy.cfm
一个简单的“extends=”Administrator”就可以工作。
没有映射逻辑。
子目录Application.cfc
extends 语句必须是文件夹的映射变量名称 (rootCfc)、一个点 (.),最后是不带 .cfc 前缀的 Proxy.cfc 模板名称 (Proxy)
我很抱歉这么冗长。我在写这篇文章时让自己很恼火——但当我试图解决这个问题时却没有那么恼火!
小心!
You absolutely can extend a cfc with mappings. I had to do it myself.
One of the most frustrating things that I have had to deal with in ColdFusion is trying to create an external application that is open to the general public and having to secure a portion of that site with an application within a subfolder and extending the logic from base application.cfc. I'll walk you through the current approach that developers use to solve this as well as showing you how to additionally use mapping when there may be a hosting provider that uses virtual directories.
This is a rather long article, if you want to jump to the condensed summary, scroll down to the bottom of this page.
Many years ago, the first time that I tried to perform this, I received the following message no matter what I tried: "Could not find the ColdFusion component or interface xxx'. In a nutshell, the problem using this approach is that both the root and the subfolders have the same name, i.e. Application.cfc, and ColdFusion can't properly identify what component to extend. Finally, after some serious investigation, someone came up with the idea to create a proxy.cfc that resides in the same root directory as the root Application.cfc, and the Application.cfc in the subfolder extends an empty proxy.cfc that extends the root cfc like so:
root directory: Application.cfc
This root Application.cfc does not extend anything
Also in the root directory: Proxy.cfc
Proxy.cfc has the following code, it's essentially empty. The only thing that the Proxy.cfc does is to extend the Application.cfc that is in the same directory:
<cfcomponent extends="Application">
</cfcomponent>
Subdirectory such as a folder named admin.
This subdirectory has another Application.cfc. Let's say that this component is responsible for securing the application and has login logic as well as debugging settings for example. This Application.cfc will extend the Proxy.cfc to gain the methods and properties of the Application.cfc in the root directory like so:
<cfcomponent displayname="Admin" extends="Proxy.cfc">
This approach was a godsend and it was heavily blogged about. Ben Nadel has made a number of very helpful posts which I will share at the bottom of this article.
This works quite well unless you're on a hosted domain or a server that uses virtual directories. In this case, we are in the same original boat in which we started from. Now we are back into the "Could not find the ColdFusion component or interface xxx' hell!
There is a solution for this tricky problem though, we need to also use mapping!
It is a common misnomer that you can't use mapping to extend components. I am not quite sure where this misconception originally came about, but it has been proven that this is just not true. There are occasions where we must use mapping to solve some annoying problems, like here.
This particular site is hosted by hostek.com. They are a fine company to deal with, but the server that my site is hosted on has some idiosyncrasies due to the directory structure. Here, when I use the Proxy.cfc method to extend the logic from the base Application.cfc to the Application.cfc in the admin folder I receive the dreaded 'could not find the ... component' error. When I first saw it I was dismayed thinking not this again, so I turned to ColdFusion CFC mapping. Mapping tells ColdFusion where to find the file and what the file relationships are.
Let's review CFC structure that was just discussed. For example, imagine the following directory structure:
root directory: i.e. www.gregoryalexander.com/
subdirectory: www.gregoryalexander.com/admin/
As discussed, we have an Application.cfc and the Proxy.cfc in the root directory, and we have the Application.cfc in the 'admin' subdirectory.
The Proxy.cfc extends the Application.cfc, also in the root directory, and the Application.cfc in the subdirectory (admin) extends the Proxy.cfc in the root directory.
root directory: contains both Application.cfc and Proxy.cfc (that extends the root Application.cfc).
subdirectory: Application.cfc (that extends Proxy.cfc).
Now we need to also add the following mapping in the root Application.cfc. This mapping logic should be near the top of the root Application.cfc, and it should not be within any of the Application.cfc event handlers (onApplicationStart, onApplicationRequest, etc). This mapping code does not need to be anywhere else other than the root Application.cfc:
<cfset this.mappings = structNew() />
<cfset this.mappings["rootCfc"] = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset this.mappings["adminCfc"] = getDirectoryFromPath( getCurrentTemplatePath() & "/admin" ) />
I used rootCfc to identify the Application.cfc in the root directory, whereas adminCfc applies to the Application in the admin directory. These variables can be named anything. Note that the "/admin" string at the end of the adminCfc mapping points to the 'admin' folder, which is a subdirectory.
Now that we have the mappings in the root Application.cfc, we need to apply them to the extends statement in Application.cfc located in the subdirectory. In the /admin/Application.cfc template use:
/admin/Application.cfc
<cfcomponent displayname="xxx" sessionmanagement="xx" clientmanagement="xx" extends="rootCfc.Proxy">
Of course, rootCfc tells the Application.cfc in the subdirectory to look for the Proxy.cfc template in the root directory. Like other 'extend' statements, you don't need to specify '.cfc' at the end of Proxy.
You don't need to use this 'extend' mapping in either the root Proxy.cfc or Application.cfc templates. They can already find each other as they are both in the same root directory.
/Proxy.cfc
<cfcomponent extends="Application">
</cfcomponent>
Summary
For the sake of absolute clarity:
root Application.cfc
Contains the mapping logic. Has the mappings for both of the root and subdirectory.
Does not use an 'extend' statement
<cfset this.mappings = structNew() />
<cfset this.mappings["rootCfc"] = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset this.mappings["adminCfc"] = getDirectoryFromPath( getCurrentTemplatePath() & "/admin" ) />
root Proxy.cfm
A simple 'extends="Administrator" works.
No mapping logic.
<cfcomponent extends="Application">
</cfcomponent>
subdirectory Application.cfc
The extends statement must be the mapping variable name of the folder (rootCfc), a dot (.), and finally the name of the Proxy.cfc template without the .cfc prefix (Proxy)
<cfcomponent displayname="Admin" sessionmanagement="yes" clientmanagement="yes" extends="rootCfc.Proxy">
My apologies for being so verbose. I annoyed myself while writing this- but not as annoyed when I was while trying to solve this problem!
Take care!
确保您的组件扩展其他组件时使用完整路径。
即产品控制器
Make sure if your components extend other components the full path is used.
ie a Products controller