Question

I've seen all kinds of solutions for extending cfcs in parent folders with access to parent files or the CF administration, but I have not seen a workable solution to extend a cfc in a "shared"/sibling folder without access to parent folders.

This solution requires access to parent folders? (Not sure what these mappings are, but I have no access to Application.cfc anyway)

This solution requires being able to create an application.cfc which doesn't work for me (creating one in myApp does nothing because the environment I'm in includes the index page in myApp and builds the from there... the client never directly calls it to fire recognition of Application.cfc)

For instance:

  • wwwroot/some/path/myApp/Shared/Base.cfc
  • wwwroot/some/path/myApp/Function/Function.cfc

I'm looking to be able to call functionality in the Base.cfc (which contains common methods used in the application) from the Function.cfc via super and extension.

I have access to all files within myApp, but not "wwwroot", "some", or "path."

In order to extend Base.cfc within Function.cfc I have to extend the full path of "some.path.myApp.Shared.Base" This would cause problems if someone renamed the myApp folder since I would have to hand edit every Function.cfc that extends that Base.cfc

What I'm looking to do it create an application specific "barrier" so if the app folder name changes it will not cause mass havoc that requires I edit all the CFC files that use functionality from the Base.cfc.

Since I can't use relative paths to the Base ("..Shared.Base") I'm wondering if there's a way to create a CFC in the myApp folder that I can extend from and alleviate the renaming headache if it were to occur or a way to give it a generic name like "myApp" and extend from there. (myApp.Shared.Base)

I do not have access to Application.cfm, nor the Coldfusion administration.

Was it helpful?

Solution

Personally I would go simpler way: incapsulate the Base into the Function.

Looks like you want to use the set of core components for some common functionality. If this is true -- incapsulation even more applicable.

Paths to objects can be built dynamically, for example (step-by-step process for easier reading):

<cfscript>

    path1 = GetDirectoryFromPath(cgi.SCRIPT_NAME);
    path2 = ListToArray(path1, "/");
    path3 = path2;
    path3[ArrayLen(path3)] = "shared";
    path4 = ArrayToList(path3, ".");
    path5 = ArrayToList(path2, ".");

    myBase = CreateObject("component", "#path4#.Base");

    myFunction = CreateObject("component", "#path5#.Function").init(myBase);

</cfscript>

In the Function create function init:

<cffunction name="init">
    <cfargument name="base">
    <cfset variables.Base = arguments.base />
    <cfreturn this />
</cffunction>

Of course, you may have strong reasons for extending, but at least this approach is not sensitive to the parent directories renaming.

OTHER TIPS

If Base.cfc doesn't extend another cfc then you may be able to include the Base.cfc file into another cfc file in your function folder.

For example create a cfc file in the function folder with content:

<cfinclude template="../shared/base.cfc" />

Then extend the new file instead of the cfc in the shared folder.

The easiest way I can see to do this is to create a symlink or junction point to the base directory in the extension function directory.

Unfortunately, it's not a pure CF solution, nor portable if you need to move your code. Hopefully, someone will have a better answer, but this could be a fallback point if none is presented.

Generate the code on app start/reset...

For example the component tag could be like so in a file that should not be run directly...

<cfabort>
<cfcomponent extends="{sharedpath}.Base">
...

then in a function in or called from application.cfc do something like this...

<cfdirectory name="codetemplates" action="list" directory="wwwroot/some/path/myApp/codetemplates" />
<cfloop query="codetemplates">
    <cffile name="temp" action="read" path="#tempfilepath##filename#" />
    <cfset newfilecontent = replace(temp.filecontent, '{sharedpath}', configvarwithrightpath) />
    <cfset filecontent = replace(newfilecontent , '<cfabort>', '') />
    <cffile name="temp" action="write" path="#livefilepath##filename#" />
</cfloop>

The other approach is to have a build process locally that you run to create the necessary code but my example above would allow you to update a config variable and update the cfc's as needed in a live environment.

Why bother putting the shared code in a separate folder? If you just put it in the same folder as your "functions" cfcs then they can all extend it using a relative path.

So instead of:

  • wwwroot/some/path/myApp/Shared/Base.cfc
  • wwwroot/some/path/myApp/Function/Function.cfc

Use:

  • wwwroot/some/path/myApp/Function/Base.cfc
  • wwwroot/some/path/myApp/Function/Function.cfc

and:

<cfcomponent extends="Base"></cfcomponent>

However, if you have/need multiple "function"-level folders, then you can do something similar. Put a Proxy.cfc inside each "function"-level folder, with this code:

<cfcomponent extends="some.path.myApp.shared.Base"></cfcomponent>

And then each cfc in the "function"-level folders would extend their local Proxy.cfc (extends="proxy"). This gives you 1 Proxy per folder, which is still not ideal, but less of a hassle than updating every cfc.

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