Published:
Warning: This blog entry was written two or more years ago. Therefore, it may contain broken links, out-dated or misleading content, or information that is just plain wrong. Please read on with caution.
Recently I was working on a set of sites that utilises a central cms which displays a different skin based on which domain it is being utilised in. The core files were replicated for each site domain which made maintenance a pain.
To cut down on maintenance I decided to use virtual directories to centralise the core code files into one set of directories (instead of a set per domain). All was going well with centralising the components, assets etc when I ran into a problem with the framework.
The Problem
The application is based on the now old (but still usefull) Fusebox 3 framework. When I changed a site to point a virtual directory to the central corefiles I started to get coldfusion "File Does Not Exist" errors for fbx_settings.cfm.
The Solution
After a long time googling and scratching my head, I was able to determine that the problem was NOT a permission error as many people suggested, but was actually a path issue. The solution was to edit the fusebox core file and add a leading "/" before the template include calls for fbx_settings.cfm and fbx_switch.cfm.
To do this open up fbx_fusebox30_CF50.cfm and locate sections 9 and 10. Look for the cfincludes for the fbx_settings.cfm and fbx_switch.cfm and add the trailing slashes. Below is a snippet taken from the file showing the fix. Skip down to the comments marked "SNEILAND"
Warning: This method assumes your application is in the webroot and not a subdirectory. If your app is in a site subdirectory you may have to add your subdirectory to the include path.
<!------------------------------------------------------------------------------------------
SECTION NINE
Attempt to include any nested fbx_Settings.cfm files, in top-to-bottom order so that variables set in children fbx_settings.cfm files can overwrite variables set in higher fbx_settings.cfm files. To prevent children fbx_settings.cfm files from overwriting variables, use CFPARAM rather than CFSET. Alternately, any child fbx_settings.cfm can CFSET a variable and lower fbx_settings.cfm files cannot overwrite it unless they use CFSET. If any fbx_settings.cfm file or directory alias cannot be found, continue on.
------------------------------------------------------------------------------------------->
<cfscript>
FB_.fullPath=ListRest(fusebox.Circuits[fusebox.TargetCircuit], "/"); //make a variable to hold the full path down to the target, excluding the root
FB_.Corepath=""; //initialize
fusebox.thisCircuit=fusebox.HomeCircuit; //current circuit, set to root now
</cfscript>
<cfloop list="#FB_.fullpath#" index="aPath" delimiters="/">
<cfscript>
FB_.Corepath=ListAppend(FB_.Corepath, aPath, "/"); //add the current circuit with / as delim
fusebox.IsHomeCircuit=FALSE; //fbx_settings.cfm files included in this loop are not the home circuit because the home circuit's fbx_Settings is needed much earlier in the process
fusebox.currentPath=FB_.Corepath & "/";
fusebox.rootPath=repeatString("../", ListLen(fusebox.currentPath, '/'));
</cfscript>
<cftry>
<cfif StructKeyExists(FB_.ReverseCircuitPath, fusebox.Circuits[fusebox.HomeCircuit] & "/" & FB_.CorePath)>
<cfset fusebox.thisCircuit=FB_.ReverseCircuitPath[fusebox.Circuits[fusebox.HomeCircuit] & "/" & FB_.CorePath] >
<cfif fusebox.thisCircuit EQ fusebox.TargetCircuit>
<cfset fusebox.IsTargetCircuit=TRUE>
<cfelse>
<cfset fusebox.IsTargetCircuit=FALSE>
</cfif>
<!--- SNEILAND: Included leading slash before #fusebox_ to make virtual directory work --->
<cfinclude template="/#fusebox.currentPath#fbx_Settings.cfm"><!---include the actual file--->
</cfif>
<cfcatch>
<cfif fusebox.suppressErrors><!--- suppressed error --->
<cfelse><cfrethrow></cfif>
</cfcatch>
</cftry>
</cfloop>
<!------------------------------------------------------------------------------------------
SECTION TEN
Now "reach down" and include the fbx_switch.cfm in the target circuit, executing fusebox.fuseaction. Store the contents of the output into a variable called fusebox.layout.
------------------------------------------------------------------------------------------->
<cfscript>
fusebox.thisCircuit=fusebox.TargetCircuit;
fusebox.IsTargetCircuit= TRUE;
FB_.fuseboxpath=FB_.fullpath; //make directory path to the target circuit
if (Len(FB_.fuseboxpath)){
//if the target circuit is NOT the root circuit
FB_.fuseboxpath=FB_.fuseboxpath & "/";
fusebox.IsHomeCircuit = FALSE;}
else
fusebox.IsHomeCircuit = TRUE;
fusebox.currentPath=fb_.fuseboxpath;
fusebox.rootPath=repeatString("../", ListLen(fb_.fuseboxpath, '/'));
</cfscript>
<cftry>
<cfsavecontent variable="fusebox.layout">
<!--- SNEILAND: Included leading slash before #FB_ to make virtual directory work --->
<cfoutput><cfinclude template="/#FB_.fuseboxpath#fbx_Switch.cfm"></cfoutput><!---include the target fbx_switch.cfm file--->
</cfsavecontent>
<cfcatch>
<cfif fusebox.suppressErrors>
<cfoutput>I could not find #FB_.fuseboxpath#fbx_Switch.cfm (or one of its components such as an included fuse) in the "#fusebox.circuit#" circuit. If you think this error is incorrect, turn off the Fusebox suppress error messages flag by setting fusebox.SuppressErrors to FALSE, and you will receive ColdFusion's "normal" error output, which could be generated by a file included from fbx_switch.cfm.</cfoutput><cfabort>
<cfelse><cfrethrow></cfif>
</cfcatch>
</cftry>
So there you have it. I hope this helps anyone who encounters the same issue.
Reader Comments
Tuesday, January 3, 2012 at 5:54:43 AM Coordinated Universal Time
Very similar circumstance and similar implementation. We had a large set of common templates and web resources (images, Javascript, CSS) shared between several domains. In each domain, I created a "/common" virtual directory and pointed it to a single folder on the server. I then CF mapped "/common" to point to this folder. This way, I could reference both templates and resources like this:
cfinclude template="/common/whatever.cfm"
and
script type="text/javascript" src="/common/js/xxx.js"