Question

UPDATE: Seems that railo doesn't have this issue at all.

UPDATE: I'm voting to close this issue as i as feel people are focusing more on the whole "does someone have a better idea splitting up large components" part of this question (which i should never have put in) then the real problem of using cfincludes with cfcomponent.

Note: this is just a simplified example of what i'm trying to do to get the idea across.

The problem I'm having is that I want to use cfinclude inside cfcomponent so that i can group like methods into separate files for more manageability. The problem I'm running into is when i try to extend another component that also uses cfinclude to manage it's method as demonstrated below. Note that ComponentA extends ComponentB:

ComponentA
==========
<cfcomponent output="false" extends="componentb">
    <cfinclude template="componenta/methods.cfm">
</cfcomponent>

componenta/methods.cfm
======================
<cffunction name="a"><cfreturn "componenta-a"></cffunction>
<cffunction name="b"><cfreturn "componenta-b"></cffunction>
<cffunction name="c"><cfreturn "componenta-c"></cffunction>
<cffunction name="d"><cfreturn super.a()></cffunction>

ComponentB
==========
<cfcomponent output="false">
    <cfinclude template="componentb/methods.cfm">
</cfcomponent>

componentb/methods.cfm
======================
<cffunction name="a"><cfreturn "componentb-a"></cffunction>
<cffunction name="b"><cfreturn "componentb-b"></cffunction>
<cffunction name="c"><cfreturn "componentb-c"></cffunction>

The issue is that when i try to initialize ComponentA I get an the error: "Routines cannot be declared more than once. The routine a has been declared twice in different templates."

The whole reason for this is because when you use cfinclude it's evaluated at RUN TIME instead of COMPILE TIME.

Short of moving the methods into the components themselves and eliminating the use of cfinclude, how can i get around this or does someone have a better idea splitting up large components?

Was it helpful?

Solution

My advice is: reanalyze your objects, try to apply to all the OOP rules and best practices (abstraction, encapsulation, modularity, polymorphism, inheritance, DRY etc.).

So basically you want component B to have method isCrunchable(), then component A extends B, and isCrunchable() is available from inheritance. Both A and B will return different states so I don't see any problem with this. If you make one class "above" which has all the methods and components A and B extend that one, you'd get your solution for "large components", but again, I'd try to crunch this a little bit more.

If this answer doesn't help, you can post real example, maybe we'll get better idea why you need this done like that.

OTHER TIPS

Not tested, but I would try putting the contents of each function in an include, but defining the functions within the component file itself. `

<cfcomponent name="a">
    <cffunction name="aa">
        <cfinclude template="componenta/functiona.cfm" />
    </cffunction>
</cfcomponent>

Good luck.

I'm with zarko on this, you should rearrange your objects, but if you must...

In CF5 I used a trick of putting functions in the request scope. This can be done by assigning the function name to a request variable of the same name, ie for a function called getLatestUpdate:

Request.getLatestUpdate = getLatestUpdate

then, before including the file with the functions, do a chech for the existence of the variable in the request scope. Only cfinclude the functions file if the request scoped variable doesn't exist.

Downside is you need to refer to the functions with the request scope prefix, and also this will only work in the traditional metaphor of a page request, it will most likely break in things like remoting calls.

I haven't tested this and YMMV.

I haven't tested it, but what about wrapping your cfinclude with something like:

<cfif NOT structKeyExists(this,"someMethodNameInIncludeFile")>
      <cfinclude....>
</cfif>

If your issue is purely about avoiding huge unwieldy objects, maybe you can break your objects down into several smaller objects. Component A could still contain methods ABCD, but Method A calls ComponentA_A method A, Method B calls ComponentA_B method B etc. Best if each subcomponent is not based on an arbitrary grouping, but a sensible grouping based on functionality. Another thing to experiment with (this is a wild stab in the dark) functions are usually described as structures attached to some scope. You can for instance delete functions from an Application.cfc by structDelete(this, onRequestStart). Maybe you can use the same approach to delete the functions previously attached to the request scope in the include?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top