Aliaspooryorik
ColdFusion ORM Book

Specifing a directory for implicitly locating circuits in Fusebox 5.5 using FUSEBOX_CALLER_PATH

I like to build my apps so that all the Controller, Model and View circuits and inside a directory off the webroot. It just seems neater to me not having lots of folders in the webroot application root.

If you are using the noxml version of Fusebox 5.5, then your model view and controller circuits need to have a directory structure which complies with the Fusebox conventions. To quote from the docs:

Fusebox attempts to find a CFC that represents the circuit by looking for:

  • controller/alias.cfc [access=”public”]
  • model/alias.cfc [access=”internal”]
  • view/alias.cfc [access=”internal”]

This means that you have to have the Controller, Model and View directories in the webroot application root. If like me, you like to have them in a subfolder, then you can edit the FUSEBOX_CALLER_PATH parameter to specify a directory, e.g:


FUSEBOX_CALLER_PATH = getDirectoryFromPath(getCurrentTemplatePath()) & "\my_fusebox_scripts\";

This means you can have a nice neat directory structure and have the time saving advantages of not having to declare each circuit in the fusebox.xml.cfm file (and of course reloading fusebox each time you add a circuit).

So, my directory structure for this blog would be (from the root of the web site www.aliaspooryorik.com):

  • Fusebox5/ (shared my multiple web apps on this domain)
  • blog/
  • blog/Application.cfc (extends Fusebox5.Application)
  • blog/index.cfm (where fusebox_caller_path is set)
  • blog/my_fusebox_scripts/
  • blog/my_fusebox_scripts/controller/
  • blog/my_fusebox_scripts/model/
  • blog/my_fusebox_scripts/view/

 It is also worth mentioning that the parsed directory location will be the same as the value set in FUSEBOX_CALLER_PATH. So for this blog it is bloc/mvc/parsed/

This post was updated: 28 March 2008, to change webroot to application root (which is what I meant originally - sorry, my mistake!)

 

 


11 comments

  1. FUSEBOX_CALLER_PATH is not intended for this usage (it is intended only to allow other applications to "include" Fusebox applications).

    Fusebox does *not* require controller/model/view directories to be in the webroot. It requires them to be in the *application* root which is generally where your index.cfm is. If your index.cfm is in a different place to the body of your application, you can use FUSEBOX_APPLICATION_PATH to specify the relative path from index.cfm to the circuits.

    However, using CFCs-as-controllers means that Fusebox still has to be able to deduce where they live in order to create them. Your options are: the CFCs have to be somewhere under your webroot (Fusebox tests the webroot path against the application path and strips the common stem then tries to create the CFCs based on what's left) or you need a mapping that is part of the directory path to the application root (Fusebox starts at the application root directory and treats it as a mapping, walking back up the tree looking at compound mappings).

    Comment by Sean Corfield – March 28, 2008
  2. Hi Sean,
    I did mean the application root and not the webroot, and I've updated the article. Sorry, my mistake, I should have spotted that.
    Thanks for pointing it out!

    Comment by John Whish – March 28, 2008
  3. There is also a fusebox parameter for the parsed directory location as well so you do not have to settle for it's default.

    Comment by Jesse – June 25, 2009
  4. Hi John,

    I am stuck and I desperately need your help. I am migrating from Fusebox 5 (xml version) to Fusebox 5.5 (non-xml version). I thought it would be a piece of cake. I read the your articles on Aliaspooryorik and looked at the sample bookstore application but there isn't just enough information out there to help me with my problem.

    I can't get my head around setting up the directory structure and I thought I'll post my query here.

    I'll try to describe my problem by first detailing how the application is currently setup using the fusebox 5 (xml version).

    The 'myapp' application is in my webroot:
    D:\ColdFusion8\wwwroot\myapp
    D:\ColdFusion8\wwwroot\myapp\application
    The controller, model and view folders are all inside the 'application' folder (D:\ColdFusion8\wwwroot\myapp\application)
    D:\ColdFusion8\wwwroot\myapp\application\controller
    D:\ColdFusion8\wwwroot\myapp\application\model
    D:\ColdFusion8\wwwroot\myapp\application\view

    I have a folder called 'common' that has the framework specific files:

    D:\ColdFusion8\wwwroot\myapp\common
    D:\ColdFusion8\wwwroot\myapp\common\core
    D:\ColdFusion8\wwwroot\myapp\common\fusebox5
    D:\ColdFusion8\wwwroot\myapp\common\controller
    D:\ColdFusion8\wwwroot\myapp\common\model
    D:\ColdFusion8\wwwroot\myapp\common\view
    D:\ColdFusion8\wwwroot\myapp\common\query
    D:\ColdFusion8\wwwroot\myapp\common\scripts
    D:\ColdFusion8\wwwroot\myapp\common\styles
    D:\ColdFusion8\wwwroot\myapp\common\ergonomics
    ...etc

    In the Application.cfc, I set the FUSEBOX_APPLICATION_PATH variable to:

    <cfset FUSEBOX_APPLICATION_PATH = "fusebox" />

    and have a folder called 'fusebox' in the application root:

    D:\ColdFusion8\wwwroot\myapp\fusebox

    The folder contains the following folders:
    D:\ColdFusion8\wwwroot\myapp\fusebox\errortemplates
    D:\ColdFusion8\wwwroot\myapp\fusebox\Lexicon
    D:\ColdFusion8\wwwroot\myapp\fusebox\parsed
    D:\ColdFusion8\wwwroot\myapp\fusebox\plugins

    and the following files:
    D:\ColdFusion8\wwwroot\myapp\fusebox\fusebox.init.cfm
    D:\ColdFusion8\wwwroot\myapp\fusebox\fusebox.xml.cfm

    In the fusebox.init.cfm, I have the following code:

    <cfset request.self = "index.cfm">
    <cfset request.myself = "#request.self#?#application.fusebox.fuseactionVariable#">

    In the fusebox.xml.cfm file I have the following code:

    <?xml version="1.0" encoding="UTF-8"?>
    <fusebox>
    <circuits>
    <circuit alias="main" path="../application/controller/" parent="" />
    <circuit alias="m" path="../application/model/" parent="" />
    <circuit alias="v" path="../application/view/" parent="" />

    <circuit alias="common" path="../application/controller/common/" parent="main" />
    <circuit alias="m_common" path="../application/model/common/" parent="m" />
    <circuit alias="v_common" path="../application/view/common/" parent="v" />
    </circuits>

    .... everything stays the same
    </fusebox>

    The index.cfm file in the application root is empty.

    And finally application.cfc file in the application root (D:\ColdFusion8\wwwroot\myapp\) looks like this:

    <cfset this.name = "myapp">

    <cfset FUSEBOX_APPLICATION_PATH = "fusebox" />

    <cffunction name="onRequestStart">

    <cfsilent>
    <cfset path = GetDirectoryFromPath(cgi.cf_template_path)>
    <cfset self = "">
    <cfset myself = "">
    <cfif right(cgi.script_name, Len("index.cfm")) NEQ "index.cfm" AND right(cgi.script_name, 3) NEQ "cfc">
    <cflocation URL="index.cfm" addtoken="false">
    </cfif>
    </cfsilent>

    </cffunction>

    <cffunction name="onRequest">
    <cfargument name="targetPage" type="string" required="true" />
    <cfinclude template="common/core/fusebox5/fusebox5.cfm">
    </cfoutput>
    </cffunction>

    This works without any problems. The task is to rewrite this using the no-xml version and Fusebox 5.5. I started working on it and this is where I've got to so far:

    D:\ColdFusion8\wwwroot\mynoxmlapp\
    D:\ColdFusion8\wwwroot\mynoxmlapp\application\
    D:\ColdFusion8\wwwroot\mynoxmlapp\application\contoller
    D:\ColdFusion8\wwwroot\mynoxmlapp\application\model
    D:\ColdFusion8\wwwroot\mynoxmlapp\application\view
    D:\ColdFusion8\wwwroot\mynoxmlapp\application\parsed

    I copied the entire 'common' folder inside the application root (D:\ColdFusion8\wwwroot\mynoxmlapp\).

    I don't have the 'fusebox' folder in the application root anymore

    The Fusebox5 folder is inside "D:\ColdFusion8\wwwroot\mynoxmlapp\common\core\

    Here is my Application.cfc file (D:\ColdFusion8\wwwroot\mynoxmlapp\Application.cfc)

    <cfcomponent extends="mynoxmlapp.common.core.fusebox5.Application" output="false">

    <cfset this.name = "mynoxmlapp" />

    <cfscript>
    FUSEBOX_PARAMETERS.allowImplicitFusebox = true;

    // the rest is taken straight from the traditional fusebox.xml skeleton:
    FUSEBOX_PARAMETERS.defaultFuseaction = "home.welcome";
    FUSEBOX_PARAMETERS.mode = "development-circuit-load";
    FUSEBOX_PARAMETERS.conditionalParse = true;
    // change this to something more secure:
    FUSEBOX_PARAMETERS.password = "";
    FUSEBOX_PARAMETERS.strictMode = true;
    FUSEBOX_PARAMETERS.debug = true;
    FUSEBOX_PARAMETERS.errortemplatesPath = "/common/core/fusebox5/errortemplates/";
    // force the directory in which we start to ensure CFC initialization works:
    FUSEBOX_CALLER_PATH = getDirectoryFromPath(getCurrentTemplatePath());
    FUSEBOX_APPLICATION_PATH = "application";
    </cfscript>

    <cffunction name="onApplicationStart" output="false">
    <cfset super.onApplicationStart() />
    <cfreturn True />
    </cffunction>

    <cffunction name="onFuseboxApplicationStart">
    <cfset super.onFuseboxApplicationStart() />
    <cfset myFusebox.getApplicationData().startTime = Now() />
    </cffunction>

    <cffunction name="onRequestStart">
    <cfargument name="targetPage" type="string" required="true" />

    <cfset super.onRequestStart(arguments.targetPage) />

    <!--- formerly in fusebox.init.cfm --->
    <cfset self = myFusebox.getSelf() />
    <cfset myself = myFusebox.getMyself() />

    <cfreturn True />
    </cffunction>

    <cffunction name="onRequestEnd" returntype="void" output="true" access="public" hint="I am executed when all pages in the request have finished processing">
    <cfargument name="targetPage" type="string" required="true" />

    <!--- Pass request to Fusebox. --->
    <cfset super.onRequestEnd(arguments.targetPage) />
    </cffunction>

    </cfcomponent>

    the index.cfm file in the application root is empty

    I created home.cfc in the controller folder (D:\ColdFusion8\wwwroot\myapp\application\controller) and declared a method called 'welcome'. I would have preferred putting the cfc in a folder called 'cHome' under the controller but I think this is not possible since it wouldn't be correct to refer to it like this:

    FUSEBOX_PARAMETERS.defaultFuseaction = "mHome.home.welcome";

    Maybe there is way set it up like that, but I don't know how to. Anyway, here is the code in the 'home' component

    <cfcomponent displayname="home" output="false" extends="main">

    <cffunction name="postfuseaction">
    <cfargument name="myFusebox" />
    <cfargument name="event" />

    <!--- do the layout --->
    <cfset myFusebox.do( action="vHome.lay_template" ) />
    </cffunction>

    <cffunction name="welcome">
    <cfargument name="myFusebox" />
    <cfargument name="event" />

    <cfset myFusebox.do( action="vHome.dsp_welcome_en", contentvariable="body" ) />
    </cffunction>

    And in the view folder (D:\ColdFusion8\wwwroot\myapp\application\controller), I created a folder called 'vHome' and in the template dsp_welcome_en, I'm just outputting message "Welcome!"

    In the same folder I created a template called 'lay_template.cfm' to layout the html

    <cfoutput>
    <hr />
    #body#
    <hr />
    </cfoutput>

    So far, so good. Everything works as I want it to. Now comes the bit for which I need your help for which I will be very very greatful.

    In the xml version, the home controller circuit.xml file had a

    <prefuseaction callsuper="true" >

    </prefuseaction>

    This was calling the top level circuit.xml file directly under the controller folder. I have created a cfc calling it "main.cfc" which is in the same folder as home.cfc and extended this in my home compoenent like this:

    <cfcomponent displayname="home" output="false" extends="main">

    This is all fine... Here comes my query. In the top level circuit.xml file there is <do> verb,

    <do action="m_common.init"/>

    'm_common' is the alias set in fusebox.xml.cfm file in fusebox5 that points to "../application/model/common/". How do I include this in main.cfc since I can't load fusebox.xml.cfm anymore in Fusebox 5.5?

    <cfset myFusebox.do( action="" ) />

    I don't know if I'm making sense. Please do let mek now if you require any further information. Any help, whatsover to point me to the right direction would be really appreciated.

    I look forward to hearing from you.

    Best regards,

    Allan

    Comment by Allan – February 09, 2010
  5. Hi Allan,

    I did reply to the enquiry you sent me through my contact form. Did you get my reply?

    It sounds like you are on the right lines, although display and layout scripts ideally should be in the view folder.

    You can do <do action="m_common.init"/> as <cfset myFusebox.do( action="common.init" ) /> if your folder is called "common" and the script is called init.cfm.

    Comment by John Whish – February 09, 2010
  6. Hi John,

    I'm afraid I didn't any response back from you in my inbox.

    I want the do action to call a cfc which is in a different folder from the one it is being called from.

    For example, I have a cfc called main in the folder: D:\ColdFusion8\wwwroot\myapp\application\controller

    I want to call a component called "commonMain" that has a method called "init" in the folder
    D:\ColdFusion8\wwwroot\myapp\common\core\controller\commonMain.cfc.

    I can't use it with your example:
    <cfset myFusebox.do( action="common.init" ) />

    because the folder common is not under the application folder. It is outside of it. Any way around it?

    Thanks in advance.
    Allan

    Comment by Allan – February 09, 2010
  7. Is there a way to declare all the circuit aliases (so they are available throught the application) like how it was possible in the fusebox xml version ex:

    <circuit alias="m" path="../application/model/" parent="" />
    <circuit alias="commonMain" path="../application/model/common/" parent="m" />

    And then use it to call the actions like so?

    <cfset myFusebox.do( action="commonMain.init" ) />

    I know I'm probably missing a step somewhere or haven't set up my application correctly. If you can throw some light it will be most appreciated.
    Thanks in advance
    Allan

    Comment by Allan – February 09, 2010
  8. If you want to call your model CFCs then you can do it with a straight CreateObject("component", "core.myCfc"). However because you are using, CFCs outside the webroot, then you need to set up a mapping which you can do in the ColdFusion administrator, or as per application mappings (which I do a lot!). Something like this:

    <cfset this.mappings["/core"] = GetDirectoryFromPath( GetCurrentTemplatePath() ) & "core" />

    Does that help?

    Comment by John Whish – February 09, 2010
  9. Hi John,

    My CFC's are in the application root (D:\ColdFusion8\wwwroot\myapp) and not in the webroot (D:\ColdFusion8\wwwroot)

    Your post was helpful but I was unable to refer to the mapping I declared in Application.cfc from inside my model cfc. Instead I added a mapping in the ColdFusion Administrator called "core" that points to "D:\ColdFusion8\wwwroot\myapp\common\core".

    <cfset this.mappings["/core"] = GetDirectoryFromPath(GetCurrentTemplatePath()) & "common\core">

    D:\ColdFusion8\wwwroot\myapp\common\core

    When I dump the 'this' scope in my cfc like so
    <cfdump var="#this#">, I only see the methods defined in the CFC. If I try to cfdump this.applicationtimeout, I get a error, "Element APPLICATIONTIMEOUT is undefined in THIS."

    Any thoughts or suggestions?

    Comment by Allan – February 10, 2010
  10. Correction: My "common" folder is in the application root (D:\ColdFusion8\wwwroot\myapp). It contains the "core" folder and inside it I have the framework specific folders.

    D:\ColdFusion8\wwwroot\myapp\common
    D:\ColdFusion8\wwwroot\myapp\common\core
    D:\ColdFusion8\wwwroot\myapp\common\core\fusebox5
    D:\ColdFusion8\wwwroot\myapp\common\core\controller
    D:\ColdFusion8\wwwroot\myapp\common\core\model
    D:\ColdFusion8\wwwroot\myapp\common\core\view
    D:\ColdFusion8\wwwroot\myapp\common\core\query
    D:\ColdFusion8\wwwroot\myapp\common\core\scripts
    D:\ColdFusion8\wwwroot\myapp\common\core\styles

    I gave up on getting the mapping in Application.cfc to work. Instead I declared a mapping called "/core" (Directory Path: D:\ColdFusion8\wwwroot\myapp\common\core ) in CF Admin and I am using it in my cfc like so:

    <cfset mainObj = CreateObject("component", "core.controller.main")>
    <cfdump var="#mainObj#">

    The above dump works correctly but the do action code below throws an error.

    <cfset myFusebox.do(action="#mainObj.init#" )/>

    Invalid token @ found on line 12 at column 228. No idea was this is.

    All I have in the main.cfc is this:

    <cfcomponent output="false">
    <cffunction name="init">
      <cfargument name="myFusebox" />
      <cfargument name="event" />
    </cffunction>
    </cfcomponent>

    Please help!

    Comment by Allan – February 10, 2010
  11. @Allan, myFusebox.do() takes the *name* of a fuseaction. You are passing it a method (essentially an object).

    myFusebox.do() can only call Fusebox controller methods that can be discovered via conventions.

    I think you're a bit confused about the difference between Fusebox controllers and the underlying "model" of the application?

    Comment by Sean Corfield – February 10, 2010

Leave a comment

If you found this post useful, interesting or just plain wrong, let me know - I like feedback :)

Please note: If you haven't commented before, then your comments will be moderated before they are displayed.

Please subscribe me to any further comments
 

Search

Wish List

Found something helpful & want to say ’thanks‘? Then visit my Amazon Wish List :)

Categories

Recent Posts