The point is to hopefully add a little clarification to the VARIABLES scope used inside of CFCs in Coldfusion 9. I’ll also be using a few other things like an init() method to further illustrate the use of the VARIABLES scope. I’ll be using simple examples of these things for demonstration purposes only. That being said, we’ll look at the first example which will demonstrate the ‘VARIABLES’ scope in a cfc as well as using an ‘init()’ method to set up a CFC. Let’s take a look at the component.
<cfcomponent displayname="Manage Person" hint="Manages the persons created." output="false"> <!--- ************************** INITIALIZE ************************** ---> <cffunction name="init" displayname="Initialize" description="Sets the variables that will need to be used throughout this component." output="false" access="public" returntype="any"> <cfset VARIABLES.name = "Matthew"> <cfset VARIABLES.haircolor = "Brown"> <cfset VARIABLES.eyecolor = "Hazel"> <cfset VARIABLES.height = "5 feet, 6 inches"> <cfset VARIABLES.weight = "130 lbs"> <cfset VARIABLES.gender = "Male"> <cfreturn THIS> </cffunction> <!--- ************************** ADD PERSON ************************** ---> <cffunction name="addPerson" displayname="Add Person" description="Creates a person object." access="public" output="false" returntype="struct"> <!--- BUILD STRUCT ---> <cfset var data = structNew()> <cfset data.success = true> <cfset data.message = ""> <cfset data.person = structNew()> <cfset data.person.name = VARIABLES.name> <cfset data.person.haircolor = VARIABLES.haircolor> <cfset data.person.eyecolor = VARIABLES.eyecolor> <cfset data.person.height = VARIABLES.height> <cfset data.person.weight = VARIABLES.weight> <cfset data.person.gender = VARIABLES.gender> <!--- RETURN STRUCT ---> <cfreturn data /> </cffunction> <!--- ***************************** SET NAME ***************************** ---> <cffunction name="setName" displayname="Set Name" description="Sets a persons name into the component." access="public" output="false" returntype="void"> <!--- ARGUMENTS ---> <cfargument name="name" displayname="Person Name" hint="The name of a person." type="string" required="true" /> <!--- SET NAME INTO THIS SCOPE ---> <cfset VARIABLES.name = ARGUMENTS.name> </cffunction> <!--- ************************** SET EYE COLOR ************************** ---> <cffunction name="setEyeColor" displayname="Set Eye Color" description="Sets the eye color of a person." access="public" output="false" returntype="void"> <!--- ARGUMENTS ---> <cfargument name="eyecolor" displayname="Person Eye Color" hint="The eye color of a person." type="string" required="true" /> <!--- SET EYE COLOR INTO THIS SCOPE ---> <cfset VARIABLES.eyecolor = ARGUMENTS.eyecolor> </cffunction> <!--- ************************** SET HAIR COLOR ************************** ---> <cffunction name="setHairColor" displayname="Set Hair Color" description="Sets the hair color of a person." access="public" output="false" returntype="void"> <!--- ARGUMENTS ---> <cfargument name="haircolor" displayname="Person Hair Color" hint="The hair color of a person." type="string" required="true" /> <!--- SET HAIR COLOR INTO THIS SCOPE ---> <cfset VARIABLES.haircolor = ARGUMENTS.haircolor> </cffunction> <!--- ************************** SET WEIGHT ************************** ---> <cffunction name="setWeight" displayname="Set Weight" description="Sets the weight of a person" access="public" output="false" returntype="void"> <!--- ARGUMENTS ---> <cfargument name="weight" displayname="Person Weight" hint="The weight of a person." type="string" required="true" /> <!--- SET WEIGHT INTO THIS SCOPE ---> <cfset VARIABLES.weight = ARGUMENTS.weight> </cffunction> <!--- ************************** SET GENDER ************************** ---> <cffunction name="setGender" displayname="Set Gender" description="Sets the gender of a person" access="public" output="false" returntype="void"> <!--- ARGUMENTS ---> <cfargument name="gender" displayname="Person Gender" hint="The gender of a person." type="string" required="true" /> <!--- SET GENDER INTO THIS SCOPE ---> <cfset VARIABLES.gender = ARGUMENTS.gender> </cffunction> <!--- ************************** SET HEIGHT ************************** ---> <cffunction name="setHeight" displayname="Set Height" description="Sets the height of a person" access="public" output="false" returntype="void"> <!--- ARGUMENTS ---> <cfargument name="height" displayname="Person Height" hint="The height of a person." type="string" required="true" /> <!--- SET HEIGHT INTO THIS SCOPE ---> <cfset VARIABLES.height = ARGUMENTS.height> </cffunction> </cfcomponent>
We have a simple cfc here with an init() method, an addPerson() method, and several setter methods for setting different attributes of a person. The scope being used here is the VARIABLES scope. This scope persists with the instance of the component. In other words, until the a new instance is created any data stored in the VARIABLES scope will be available to all functions inside the component.
The init() method is called when we create an instance of the component. Upon creation we simply set a few pieces of data into the VARIABLES scope preparing the component to use any of this data in any of the following methods. In this case I go ahead and simply create a default person object, but could easily leave this data blank and rely on the set methods to fill in the person object attributes.
The next method is the addPerson() method which just compiles all of the attributes that make a person object and store it into a struct called ‘data’. Notice though that none of the values of a person are set in this method. It’s only job is to lump it all into a struct. We can do this because our data is stored in the VARIABLES scope.
The remaining functions just set data into the VARIABLES scope. Notice that they simply accept a value as an ARGUMENT, and then take that value and set it into the VARIABLES scope. This essentially overrides the value set initially in the init() method. Let’s look now at how this would be called from the .cfm page.
<!--- CREATE AN INSTANCE OF OUR OBJECT --->
<cfset person_obj = createObject("component", "my_tools.inheritance.cfcs.manage_person").init()>
<!--- ADD A PERSON OBJECT --->
<cfset person = person_obj.addPerson()>
<!--- DUMP THE PERSON OBJECT --->
<cfdump var="#person#">
First we create an instance of our component using the ‘createObject()’ method. Not only do we create an instance, but we also go on and run the ‘init()’ method as well. The init() method returns the THIS scope. This is very important to do. If you do not return the THIS scope when running an init() method during the instance creation you won’t get anything back to play on. So for example, if I didn’t return the THIS scope I wouldn’t be able to call the addPerson() method because I technically don’t have it to call because it was never returned. If you do not call a method upon creating an instance Coldfusion will by default return everything that the component has to offer.
So if we were to simply dump our component instance ‘person_obj’ we would get the following. To get the following output I temporarily changed the return on the init() method to VARIABLES so we could see the variables that were created upon creating the component instance. Dumping the instance when the we return the appropriate THIS scope only returns the available methods. This makes sense since we can’t access any data stored in the component’s VARIABLES scope outside of the component itself.
Anyways, this was just a small portion of the actual struct, but you get the idea. Point being when we look at the VARIABLES scope of our cfc we see the data that was set in the init() method as well as each function that is also stored in the VARIABLES scope by default under the name of the function.
All is well so far. Now let’s look at what is returned when we add a person. Remember that in the init() method we create a default person. Since we are not running any setter methods our addPerson() method will simply return the default person object. So given the above code, when we dump the ‘person’ variable we get the following.
Now let’s say we want to create a new person. To do this we will need to call our setter methods and pass them the attributes of our new person. To create our new person our code would look like the following.
<!--- CREATE AN INSTANCE OF OUR OBJECT --->
<cfset person_obj = createObject("component", "my_tools.inheritance.cfcs.manage_person").init()>
<!--- SET NEW HAIR COLOR --->
<cfset person_obj.setName("Adriana")>
<cfset person_obj.setEyeColor("Brown")>
<cfset person_obj.setHairColor("Black")>
<cfset person_obj.setWeight("105 lbs")>
<cfset person_obj.setGender("Female")>
<cfset person_obj.setHeight("5 feet, 4 inches")>
<!--- ADD A PERSON OBJECT --->
<cfset person = person_obj.addPerson()>
<!--- DUMP THE PERSON OBJECT --->
<cfdump var="#person#">
Our new person object now looks like the following.
Point being here that we have just used our setter methods to manipulate the VARIABLES scope in the cfc to reflect the attributes of a different person. Then we use our same addPerson() method to compile those attributes into an object, or more specifically a struct. When all is said and done, the main thing to keep in mind is that data in the VARIABLES scope persists the duration of the component instance and is available for use from within the component.


