在子目录中扩展application.cfc

13

我有以下两个文件,希望第二个文件扩展第一个文件:

  1. wwwroot\site\application.cfc
  2. wwwroot\site\dir\application.cfc

然而,当我要为第二个文件声明组件时,我不确定在 extends 属性中应该放什么。我的问题是,几个开发站点(共用一个 SVN 存储库)都在同一个 ColdFusion 实例上运行,所以我不能像这样在 CF 管理界面中创建映射:

<cfcomponent extends="site.application">

然而,ColdFusion 不喜欢以下内容:

<cfcomponent extends="..application">

或者任何动态输入,例如:
<cfcomponent extends="#expandpath('..').#application">

创建一个运行时映射(例如这里)似乎也不可能。在基本的application.cfc中创建它是无用的,因为在继承cfc被声明时,该代码尚未执行。我无法在继承组件定义之前创建映射,因为还没有应用程序可以附加它。

有没有办法引用父目录来完成我的extends?

编辑以澄清:ApplicationProxy解决方法由于上面加粗的文字而不起作用。现在,作为一种解决方法,我们简单地不将\dir\application.cfc检入SVN,以便每个开发人员都可以保留扩展自己根application.cfc的版本。显然,这并不理想。

4个回答

16

Sean Corfield写了一篇博客文章,解释如何扩展根Application.cfc。

以下是从该文章中复制的相关信息。


这是您的根CFC /Application.cfc:

<cfcomponent>

    <cfset this.name = "cf7app" />
    <cfset this.sessionmanagement = true />

</cfcomponent>

这是你的代理CFC /ApplicationProxy.cfc:

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

这个子目录完全是空的,仅仅用来为你的根目录/Application.cfc创建一个别名。这是你的子目录CFC /app/Application.cfc:

<cfcomponent extends="ApplicationProxy">

    <cffunction name="onSessionStart">
        <cfoutput><p>app.Application.onSessionStart()</p></cfoutput>
        <cfset session.counter = 0 />
    </cffunction>

    <cffunction name="onRequestStart">
        <cfoutput><p>app.Application.onRequestStart()</p></cfoutput>
        <cfdump label="application" var="#application#"/>
    </cffunction>

</cfcomponent>

每个站点的根目录应该有自己的主应用程序:
/site1/Application.cfc
/site2/Application.cfc
/site3/Application.cfc

所有这些应用都是独立的应用程序,它们之间没有共享任何内容。
如果这些单独的站点需要有子应用程序,则需要在主应用程序旁边添加ApplicationProxy.cfc。
e.g.
/site1/ApplicationProxy.cfc
/site2/ApplicationProxy.cfc

然后,对于每个子应用程序,您都需要扩展代理:

e.g.
/site1/subA/Application.cfc
/site1/subB/Application.cfc
/site2/subA/Application.cfc

如果站点根目录不是Web根目录,则需要将站点根目录映射到Web根目录。如果您的映射名称为foo,则应扩展“foo.application”。 - Adam Tuttle
不要创建到“/devsite1”的映射。创建一个“/common”映射,并在“/devsite1/application.cfc”和“/devsite2/dir/application.cfc”中都引用“common.ApplicationProxy”。 - Peter Boughton
我刚刚编辑了答案,试图解释如何在具有自己子应用程序的多个站点上工作,尽管我仍然不确定您试图实现什么。 - Peter Boughton
我认为你应该将名称属性更改为DisplayName,Name不是cfcomponent标记的属性。至少根据Adobe文档是这样的。也许我错过了什么? - osekmedia
代码只是从引用链接中复制的,但你说得对,name不是一个有效的属性(我认为这是CFMX6/7时代的遗留问题)。然而,displayname同样没有用处,即使它是一个支持的属性,也没有必要使用它。 - Peter Boughton
显示剩余3条评论

4
以下代码对我有效。但我注意到一个问题,就是application.cfc似乎被缓存了,因此对父应用程序cfc的更改可能不会反映出来。我通过对子应用程序cfc进行微小的更改来解决这个问题。
<cfcomponent output="false">
        <cfset variables.higherPath = ReReplace(GetMetaData(this).name,"\.[^\.]+\.[^\.]+$","") />
        <cfset variables.extendApp = CreateObject("component", "#variables.higherPath#.Application") />

        <cfloop item="variables.key" collection="#variables.extendApp#">
            <cfif IsCustomFunction(variables.extendApp[variables.key])>
                <cfset super[variables.key] = variables.extendApp[variables.key]>
            <cfelse>
                <cfset this[variables.key] = variables.extendApp[variables.key] >
            </cfif>
        </cfloop>
        <cffunction name="onApplicationStart" output="false">
            <cfset super.onApplicationStart() />
        </cffunction>

3

我知道这是一个老话题,但我找到了一种方法(在我的测试中似乎有效),可以不使用CF管理员映射来完成。

您可以通过在子Application.cfc中使用扩展的相对路径添加每个应用程序映射来实现此目的:

<cfcomponent extends="cms.Application" output="false">
<cfset this.mappings["/cms"] = expandPath(getDirectoryFromPath(getCurrentTemplatePath()) & "../../../../")>
<cflog text="#getMetadata(this).extends.path#">
</cfcomponent>

是的,这种方法感觉有点不正规,但似乎可以起作用。


1
这对我似乎不起作用。你能进一步解释一下,并列出你使用的ColdFusion版本吗?看起来映射在Application.cfc开始处理之后才会被定义,但是这是不可能的,因为映射是必需的,以便它能够通过第一行。 - Nicholas

0

Edward,等人,我在下面的帖子中提到了你的评论。请参见https://gregoryalexander.com/blog/2021/1/30/Extending-Applicationcfcs-using-mappings-and-proxies

你绝对可以使用映射来扩展cfc。我自己也不得不这样做。

在ColdFusion中,我最让人沮丧的事情之一是尝试创建一个向公众开放的外部应用程序,并需要使用子文件夹中的应用程序来保护该站点的一部分,并从基本application.cfc扩展逻辑。我将向您展示当前开发人员用于解决此问题的方法,以及如何在可能存在虚拟目录的托管提供程序时使用映射。

这是一篇相当长的文章,如果您想跳转到简要摘要,请滚动到本页底部。

很多年前,我第一次尝试执行此操作时,无论我尝试什么,都会收到以下消息:“找不到 ColdFusion 组件或接口 xxx”。简而言之,使用这种方法的问题在于根目录和子文件夹具有相同的名称,即 Application.cfc,ColdFusion 无法正确识别要扩展的组件。最终,在进行了一些严肃的调查后,有人想出了一个主意,即创建一个代理.cfc,它驻留在与根 Application.cfc 相同的根目录中,而子文件夹中的 Application.cfc 扩展了一个空的代理.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”的地狱!

然而,对于这个棘手的问题,有一个解决方案,我们需要使用映射!

人们普遍认为不能使用映射来扩展组件,这是一个常见的误解。我不确定这个误解最初是从哪里来的,但已经证明这不是真的。有时候我们必须使用映射来解决一些恼人的问题,就像这里一样。

这个网站是由hostek.com托管的。他们是一家很好的公司,但我的网站所在的服务器由于目录结构存在一些特殊性。在这里,当我使用Proxy.cfc方法将基本Application.cfc中的逻辑扩展到admin文件夹中的Application.cfc时,我会收到可怕的“找不到...组件”错误。当我第一次看到它时,我感到沮丧,认为不要再出现这种情况了,所以我转向了ColdFusion CFC映射。映射告诉ColdFusion文件在哪里以及文件之间的关系。
让我们回顾刚刚讨论过的CFC结构。例如,想象以下目录结构:
根目录:即www.gregoryalexander.com/ 子目录:www.gregoryalexander.com/admin/ 如讨论所述,我们在根目录中有一个 Application.cfc 和一个 Proxy.cfc,并且我们在“admin”子目录中还有一个 Application.cfc。Proxy.cfc 扩展了位于根目录中的 Application.cfc,而子目录(admin)中的 Application.cfc 则扩展了位于根目录中的 Proxy.cfc。
根目录包含 Application.cfc 和扩展根 Application.cfc 的 Proxy.cfc。子目录包含扩展 Proxy.cfc 的 Application.cfc。
现在我们还需要在根 Application.cfc 中添加以下映射。这个映射逻辑应该放在根 Application.cfc 的顶部附近,而不应该放在任何 Application.cfc 事件处理程序(onApplicationStart、onApplicationRequest 等)中。这个映射代码不需要出现在除根 Application.cfc 之外的任何其他地方:
我使用 rootCfc 来标识位于根目录中的 Application.cfc,而 adminCfc 适用于 admin 目录中的应用程序。这些变量可以命名为任何名称。请注意,“/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模板中使用此“extend”映射。它们已经可以相互找到,因为它们都在同一个根目录中。

/Proxy.cfc

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

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

子目录 Application.cfc 在 extends 语句中,必须使用文件夹的映射变量名(rootCfc),一个点(.),最后是没有 .cfc 前缀的 Proxy.cfc 模板的名称

非常抱歉我写得如此啰嗦。在解决这个问题时我很生气,但没有现在这么生气!

请保重!


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