Skip to content

Instantly share code, notes, and snippets.

@tmeers
Last active August 29, 2015 14:13
Show Gist options
  • Save tmeers/6ccc5e90bbe4f90adf40 to your computer and use it in GitHub Desktop.
Save tmeers/6ccc5e90bbe4f90adf40 to your computer and use it in GitHub Desktop.
ColdFusion CreateObject
I'm hosting multiple (near identical) applicaitons under the ./applications/ folder.
For this example I'm using [testing] to represent the individual applicaitons.
I need to replace this:
<cfset variables.employeeObj = CreateObject("component","applications.psctest.includes.employee")>
with something less unique to the application. Perhaps basing the string literal:
"applications.[testing].includes.employee"
with an application setting in application.cfc in the root of each applicaiton?
Or creating the instance of these different "variables.employeeObj" objects in the applicaiton.cfc?
Either way I'm trying to cut down on the differeces between applications. The current model makes it
very difficult to update code and move it to the different applications.
For an example, I have a basic cfc (booth.cfc) calling a function I'm using in many other places.
./applications/[testing]/booth/booth.cfc
<cfcomponent output="no">
<!--- create instances of the objects that will be needed. --->
<cfset variables.employeeObj = CreateObject("component","applications.psctest.includes.employee")>
<cffunction name="getEmployeeName" access="remote" returntype="string" returnformat="plain">
<cfargument name="employeeID" type="string" required="yes">
<cfreturn employeeObj.getEmployeeName(arguments.employeeID)>
</cffunction>
</cfcomponent>
./applications/[testing]/includes/employee.cfc
<cfcomponent output="no">
<cffunction name="getEmployeeName" access="public" returntype="string">
<cfargument name="employeeId" type="string" required="yes">
<cfquery name="qGetEmpNameloginEmp" datasource="Intranet">
-- get employee data --
</cfquery>
<cfreturn qGetEmpNameloginEmp.EmployeeFullName>
</cffunction>
</cfcomponent>
@cfvonner
Copy link

Can you add a little folder tree sample to see how the code is organized? Do you have a single Application.cfc file that all applications share, or is each application completely independent?

@tmeers
Copy link
Author

tmeers commented Jan 15, 2015

Each application is independent. So the folders have an application.cfc and the overall structure would be like this:

root
└───applications
    │
    ├───[app 1]
    │   application.cfc
    │   │
    │   └───booth
    │   │   booth.cfc
    │   │   ...
    │   └───includes
    │   │   employee.cfc
    │   │   ...
    ├───[testing]
    │   application.cfc
    │   │   ...
    │   └───booth
    │   │   booth.cfc
    │   │   ...
    │   └───includes
    │   │   employee.cfc
    │   │   ...

Each application in this example is wrapped in square brackets. So [app 1] and [testing].

@cfvonner
Copy link

I'm working on something for you. i'll post it in a few hours.
-Carl

@cfvonner
Copy link

OK. So in each application.cfc, you can define mappings in the pseudo-constructor at the top, using this.mappings. There is an example at the bottom of this page: http://www.learncfinaweek.com/week1/Application_cfc/

Also, Ben Nadel's blog post is good too: http://www.bennadel.com/blog/2519-expandpath-works-with-coldfusion-s-per-application-mappings.htm

component {
   this.name = "app1";
   this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
    this.mappings = {
        "/booth" = "#this.directory#booth/";
        "/includes" = "#this.directory#includes/";
    };
    ...

So what this does is figure out the application root directory from the current template (in this case, application.cfc) and put it into this.directory. Then it uses that directory to create mappings (think of them as aliases) that point to specific subfolders of the application directory.

So now in booth.cfc, you can use the mappings to more succinctly point to the various subfolders. Just replace this:

<cfset variables.employeeObj = CreateObject("component","applications.psctest.includes.employee")>

with this:

<cfset variables.employeeObj = CreateObject("component","includes.employee")>

The nice thing about this approach is that it works as is, no matter what the name of the application's parent folder is. This same code will work for \root\applications\app1, \root\applications\app2, \root\applications\foo, or whatever.

@bdw429s
Copy link

bdw429s commented Jan 16, 2015

You can't do 100% script CFCs until ColdFusion 9. In CF8, you can just slap a cfscript tag inside your component declaration and then pretend it's a script CFC.

Remember, this is just syntax-- all functionality is still available to you regardless of whether you use script or tags.

<cfcomponent>
  <cfscript>
    this.name = "app1";
    this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
   this.mappings = {
      "/booth" = "#this.directory#booth/",
     "/includes" = "#this.directory#includes/"
    };

    function foobar() {
      return false;
    }

    function foobar2() {
      return false;
    }
  </cfscript>
</cfcomponent>

@tmeers
Copy link
Author

tmeers commented Jan 16, 2015

Because of twitter conversation.

Something tells me my version of ColdFusion isn't going to let me do <cfscript> component { .. } </cfscript> in my Apalication.cfc... Boo

— Tim 'Paul' Meers (@_neckbeard) January 16, 2015
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

I've updated my code with this:

<cfcomponent displayname="Application" output="true" hint="Handle the application."> 
    <cfscript>
    component { 
           this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
            this.mappings = {
                "/includes" = this.directory & "includes/";
            };
        }
    </cfscript>

But am receiving the error:

Invalid CFML construct found on line 3 at column 19.  
ColdFusion was looking at the following text:
{

The CFML compiler was processing:

A script statement beginning with component on line 3, column 9.
A cfscript tag beginning on line 2, column 10.

@tmeers
Copy link
Author

tmeers commented Jan 16, 2015

Even just wrapping it in an undecorated tag I'm still getting the same compiler error;

<cfcomponent>
    <cfscript>
    component { 
           this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
            this.mappings = {
                "/includes" = this.directory & "includes/";
            };
        }
    </cfscript>
</cfcomponent>

@bdw429s
Copy link

bdw429s commented Jan 16, 2015

Look at my code sample above. You don't re-declare the component- it's already declared via the cfcomponent tag.

<cfcomponent>
</cfcomponent>

is the equivalent of

component {
}

@tmeers
Copy link
Author

tmeers commented Jan 16, 2015

Ahhh! I read right over that. But still an error. It's not liking the opening curly brace in the mappings now:

<cfcomponent>
    <cfscript>
           this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
            this.mappings = {
                "/includes" = this.directory & "includes/";
            };
    </cfscript>
</cfcomponent>

Error

Invalid CFML construct found on line 4 at column 41.  
ColdFusion was looking at the following text:
{

The CFML compiler was processing:

A script statement beginning with this.mappings on line 4, column 25.
A cfscript tag beginning on line 2, column 10.

@bdw429s
Copy link

bdw429s commented Jan 16, 2015

You have a syntax error. Remove the semi-colon from the end of the middle line.

this.mappings = {
  "/includes" = this.directory & "includes/"
};

ColdFusion 8 has crap struct literal support though. You may find places where you just need to use the older, uglier syntax of declaring structs:

this.mappings = structNew();
this.mappings[ "/includes" ] = this.directory & "includes/";

You also should really just upgrade to something newer than 2007 :)

@tmeers
Copy link
Author

tmeers commented Jan 16, 2015

THAT is what I needed!!

Final working version:

    <cfscript>
        this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
        this.mappings = structNew();
        this.mappings[ "/includes" ] = this.directory & "includes/";
    </cfscript>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment