I am working on a project and in this project there are many variables I want to store in an xml file. I could just stick them all in there as key/value pairs but I enjoy some type of structure in my application settings (as well as life). Typically I break my settings into logical groups such as the example settings.xml file below.
settings.xml2<settings>
3<application>
4 <name>mysite</name>
5 <version>v 0.1 {alpha}</version>
6 <url>http://www.mysite.com</url>
7 <secure>https://mysite.com</secure>
8</application>
9<database>
10 <dsn>mydsn</dsn>
11 <dbtype>mssql</dbtype>
12</database>
13<email>
14 <username>me</username>
15 <password>pass</password>
16 <server>mail.mysite.com</server>
17</email>
18</settings>
I am sure this is nothing to everyone but I came across something this problem today and could not find a quick solution. This example above would be very easy to parse int o some type of structure but what if I wanted to add a new section such as cart. I do not want to make changes to my Settings component so everything needs to be dynamic. For every grouping I want to create a separate structure. I whipped up this quick Setting component that will allow you read the XML file above with no regards of what it contains. I know I am re inventing the wheel here but hopefully this will help someone, on to the code.
Settings.cfc2
3 <cfset variables.settings = "">
4 <cfset variables.configPath = "">
5
6 <cffunction name="init" access="public" output="false" returntype="settings">
7 <cfargument name="path" type="string" required="true" hint="Absolute Path to config file.">
8 <cfset variables.settings = structNew()>
9 <cfset variables.configpath = arguments.path>
10 <cfreturn this>
11 </cffunction>
12
13 <cffunction name="read" access="public" output="true" returntype="struct"
14 hint="I will return a structure containing all application seetings.">
15 <cfset var xml = "">
16 <cfset var xmldoc = "">
17 <cftry>
18 <cffile action="read" file="#variables.configPath#" variable="xml"/>
19 <cfcatch type="any">
20 <cfthrow message="Invalid path to settings file.">
21 </cfcatch>
22 </cftry>
23 <cfset xmldoc = xmlParse(xml)>
24
25 <cfloop collection="#xmldoc.settings#" item="parent">
26 <!--- for each parent add a new item to our structure --->
27 <cfset structInsert(variables.settings,parent,structNew())>
28 <cfloop collection="#xmldoc.settings[parent]#" item="child">
29 <cfset structInsert(variables.settings[parent],child,xmldoc.settings[parent][child].xmlText)>
30 </cfloop>
31 </cfloop>
32
33 <cfreturn variables.settings>
34 </cffunction>
35
36 <cffunction name="set" access="public" output="false" returntype="void"
37 hint="I will set a key/pair value ">
38 <cfargument name="parent" type="string" required="true">
39 <cfargument name="key" type="string" required="true">
40 </cffunction>
41
42 <cffunction name="get" access="public" output="false" returntype="void">
43 <cfargument name="parent" type="string" required="true">
44 <cfargument name="key" type="string" required="true">
45 </cffunction>
46
47</cfcomponent>
In a nutshell the read method is where the magic happens and here is what it does.
- Read in your xml settings file.
- Parse it
- Loop the settings node
- For each child of settings (grouping such as application & database) add a new key to our settings structure and initialize a new structure as its value
- Loop that key and insert a new key/value pair into your new structure that was just created.
2 <cfset settingsObj = createObject("component","settings").init(path)>
3 <cfset settings = settingsObj.read()>
4
5 <cfdump var="#settings#">
One more quick note about xml settings files. I tend to keep this out of the web root for security reasons. In my new application I am using the following structure.
- /admin - admin area (admin.mysite.com)
- /cfc - all components
- /config - coldspring and settings xml
- /www - public folder
- Application.cfc
