-
-
Save tmeers/6ccc5e90bbe4f90adf40 to your computer and use it in GitHub Desktop.
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> |
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].
I'm working on something for you. i'll post it in a few hours.
-Carl
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.
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>
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.
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>
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 {
}
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.
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 :)
THAT is what I needed!!
Final working version:
<cfscript>
this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
this.mappings = structNew();
this.mappings[ "/includes" ] = this.directory & "includes/";
</cfscript>
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?