Environment-Specific Application Scope Variables
Posted: May 15th, 2009 | Author: Christopher Vigliotti | Filed under: ColdFusion | 2 Comments »If you don’t know what an Application.cfc file is or how to use it I suggest that you start with this
excellent Application.cfc Tutorial & Reference over at Ben Nadel’s blog.
There are number of approaches for managing environment-specific variables for your applications. One is to store them into an external XML file. I would imagine that there is an increased processor overhead associated with this path (it may be marginal), and there is the extra code of parsing the XML data to get your variables. One approach that’s worked well for me is to define the variables for each of my applications environments in a function in my Application.cfc files. This function detects which environment it’s being run in and sets the variables accordingly. Peep this out…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | <cfcomponent hint="I am an Application.cfc file."> <!--- properties get declared here ---> <!--- onApplicationStart ---> <cffunction name="onApplicationStart" access="public" hint="built-in method in Application.cfc"> <cflock scope="Application"> <cfscript> declareApplicationScopeVariables(); </cfscript> </cflock> </cffunction> <!--- declareApplicationScopeVariables---> <cffunction name="declareApplicationScopeVariables" access="package" hint="called by onApplicationStart, selects an environment and sets environment-specific Application variables here" output="false" returntype="void"> <cfscript> var localScope = StructNew(); localScope.env= StructNew(); localScope.useDefaultEnvironment = true; localScope.defaultEnvironmentStructName = ""; // development variables localScope.env.dev = StructNew(); localScope.env.dev.serversList = "127.0.0.1,localhost,dev.cfcheese.whatever"; localScope.env.dev.datasource = "CheesyDB_dev"; localScope.env.dev.isDefaultEnvironment = false; // test variables localScope.env.test = StructNew(); localScope.env.test.serversList = "test.cfcheese.whatever"; localScope.env.test.datasource = "CheesyDB_test"; localScope.env.test.isDefaultEnvironment = false; // production variables localScope.env.prod = StructNew(); localScope.env.prod.serversList = "cfcheese.whatever"; localScope.env.prod.datasource = "CheesyDB"; localScope.env.prod.isDefaultEnvironment = true; /* define your environment here localScope.env.yourEnvironmentName= StructNew(); localScope.env.yourEnvironmentName.serversList = "cfcheese.whatever"; localScope.env.yourEnvironmentName.datasource = "CheesyDB"; localScope.env.yourEnvironmentName.isDefaultEnvironment = false; */ // loop through each environment for(localScope.loopItem IN localScope.env){ // if cgi.SERVER_NAME matches one of the environments if(ListFindNoCase(localScope.env[localScope.loopItem].serversList, cgi.SERVER_NAME)){ // set environment-specific variables here Application.datasource = localScope.env[localScope.loopItem].datasource; // we have a match! do not set vars from the default environment localScope.useDefaultEnvironment = false; } // if the environment is the default environment, note it here if(localScope.env[localScope.loopItem].isDefaultEnvironment IS true){ localScope.defaultEnvironmentStructName = ""; } } // if no environment matches, default to production if(localScope.useDefaultEnvironment IS true){ Application.datasource = localScope.env[localScope.defaultEnvironmentStructName].datasource; } // lastly, declare application-agnostic variables here ("application-agnostic"?!) Application.cfcPath = "inc.cfcs."; </cfscript> </cffunction> <!--- the rest of my Application.cfc code goes here ---> </cfcomponent> |
When the application starts, it calls declareApplicationScopeVariables(). This function defines and sets Application scope variables that are 1) the same across all environments, as well as variables that are 2) different in each environment.
I make no claims that this is the best approach. I’m open to doing this in a totally different fashion. Hit me up in the comments if you have a suggestion.
I do something quite similar. Although, I move your utility method out into its own component: Config.cfc; which essentially does the same thing you are doing. Then, rather than caching the individual properties in the APPLICATION scope, I just cache the Config.cfc instance.
I like moving it into a CFC because I can add some additional utility methods for readability like:
IsLive()
CleanWebPath()
CleanServerPath()
But, like I said, very much like what you’re doing and its worked well for me.
Hey thanks for the comment Ben! I like the idea of organizing your configuration variables into a new CFC.