CFCs for the common developer
Recently in the SitePoint ColdFusion forums there was a nice little discussion about CFC’s and how everyone who explains them or teaches them throws in a lot of buzzwords which does more to confuse people then to help them along. Now I know this happens because I’m guilty of it as well as a lot of other seasoned ColdFusion developers. So hopefully with this post I can help move those who are interested but unsure about CFC’s into this wonderful world.
So what is a CFC? First off a CFC is actually called a ColdFusion Component and at its most simple terms it’s just a ColdFusion template (aka a ColdFusion page or file) but instead of a .cfm or .cfml extension it has a .cfc extension.
Now just because a file has a .cfc extension on it doesn’t make it a CFC right away. Once you have your .cfc file created you do have to write some code. Typically a CFC is made up of 2 or 3 basic parts. The first part is the actually CFC tags and they look something like this:
<cfcomponent displayname="Greeting" hint="I'm a greeting CFC"> </cfcomponent>
There is only one tag which makes a CFC and that is the CFComponent tag, which requires both an opening and closing tag. Now from this point you can add some code inside these tags or you can leave it blank, which is left blank will give you a blank CFC. You’ll notice that my CFComponent tag has two additional attributes displayname and hint. These are descriptive attribute in that they don’t DO anything but they DO describe the CFC. The displayname attribute is the name which shows up when ColdFusion auto generates documentation for a CFC and the hint is the description. We’ll talk more about documentation later though :)
So what can go inside these CFComponent tags? Pretty much any ColdFusion tags you normally use can be used inside the CFComponent tags. Typically though a CFC is a collection of functions, using the CFFunction tag, and sometimes properties, using the CFProperty tag.
Now I’m sure you’ve seen the CFFunction tag and if you’ve done any extensive development with CF MX (version 6) or later you’ve used your fair share of CFFunction tags. For CFC’s you use the same syntax as you would anywhere else in your code. For example if I wanted a function to return a general greeting for me I might write it as:
<cffunction name="getGreeting" output="false" returntype="string" description="Returns a greeting string"> <cfargument name="visitor" required="no" type="string" displayname="Visitor String" hint="The Visitors name"> <cfif IsDefined('arguments.visitor') AND Len(Trim(arguments.visitor))> <cfreturn 'Welcome ' & arguments.visitor & '! I hope you enjoy your stay.'> <cfelse> <cfreturn 'Welcome guest! Enjoy your visit and please come back soon.'> </cfif> </cffunction>
Now this code is a bit beefier so I’ve numbered each line so we can walk through it without me having to reprint it (and risk a cut and paste mistake!). So line 1 sets up our function with the CFFunction tag and within this tag I’ve used 4 attributes. The name attribute is the wording I’ll use to reference or call this function, in this case it’s called getGreeting. Next I set the output attribute to false which tells ColdFusion to treat this function as if it was inside a CFSilent tag, thereby forcing only the text I specify in the CFReturn tag to be output when the function is called. If I set the output to true then any code I had inside this function (including HTML) would show up when this function was processed. 99% of the time you want to make sure you set the output to false unless you have a reason for HTML and CFML to be processed and shown without the use of a cfreturn tag. (I haven’t come across this yet, but I’m sure someone has). The next attribute is the returntype which I’ve set to string. Setting a return type is useful because it allows ColdFusion to error check the data which a particular function returns. So if i accidentally returned an array, or query ColdFusion would error out telling me that they type of data returned from this function was not of type string. It’s very rare that my functions actually return anything other than what i tell it to but when you get into complex CFC’s which are returning all kinds of data types setting the return type can be very helpful. Now you don’t HAVE to set a returntype but if CFC’s and Functions are new to you I’d recommend you do until you have a solid grasp of what exactly is happening and why. Ok the last attribute we set is the description and this is just used to describe to a fellow developer what is going on, and if you use ColdFusion to create your docs (more on that later) this will be output in those docs, so always try to describe your functions.
Line 2 is a CFArgument tag. Functions have the ability to take in data and then process or do something with that data, this passed in data is referred to as a argument and functions can have multiple arguments passed in. The CFArgument tag above consists of 5 attributes. the name attribute is the name of the argument being passed in, in this case it’s visitor. Next we have a required attribute which tells ColdFusion if this argument is required for the function to work properly. In this case we have set the value of the required attribute to no so we could call this function and not pass in any arguments. Next we have the type attribute which tells ColdFusion what kind of data this argument is going to be. Again by specifying a type ColdFusion will check the passed in data and if it’s not of the specified type it will return an error. In this case we told our function that visitor will be of type string so it will allow just about anything in. The last two attributes displayname and hint are again used to help my fellow developers know what is going on and also for documentation.
Line 3 starts our if statement where we check to see if my visitor argument was passed in our not. When using functions all variables passed in are in the arguments scope which is a scope only accessible by code inside the opening and closing function tags. Here i use the IsDefined function to see if the variable exists and if it does exist then the next bit of code to execute is my Len() and Trim() functions. I’ve nested the trim function inside the len function so that any white space or carriage returns in the visitor variable data will be stripped out and i will only get a length value for the actual data passed in the string. By doing the trim and then the len i can ensure that a bunch of blank spaces, tabs, or returns weren’t sent in and that i actually have a string of usable data. I could have written this bit of code as Len(Trim(arguments.visitor)) GT 1 and it would have the same effect as Len(Trim(arguments.visitor)) since the later will return either zero or some positive number.
OK line 4 has a CFReturn tag and you should notice there are no attributes here. the CFReturn tag takes an expression, in this case a string, and it’s this expression which is returned by the function. Here I’ve typed in a little greeting and used the & symbol to concatenate two strings around whatever data was passed into my function via the visitor variable.
line 5 is our cfelse statement so if arguments.visitor did not exist OR the length of the value for arguments.visitor after it was trimmed was 0 then line 6 will be executed.
line 6 is another CFReturn tag but this time it just a simple text sentence with no variables being concatenated like we saw on line 4.
Line 7 closed out our CFIF block and line 8 will close out our CFFunction tag. So if we put our component code with our function code it should look like:
<cfcomponent displayname="Greeting" hint="I'm a greeting CFC"> <cffunction name="getGreeting" output="false" returntype="string" description="Returns a greeting string"> <cfargument name="visitor" required="no" type="string" displayname="Visitor String" hint="The Visitors name"> <cfif IsDefined('arguments.visitor') AND Len(Trim(arguments.visitor))> <cfreturn 'Welcome ' & arguments.visitor & '! I hope you enjoy your stay.'> <cfelse> <cfreturn 'Welcome guest! Enjoy your visit and please come back soon.'> </cfif> </cffunction> </cfcomponent>
So now you have a very basic CFC. You can copy this text into your editor of choice if you want and save the file as greeting.cfc. So now that you have this CFC what can you do with it? how do you call it? what’s the point? All of these are great questions but you’re going to have to wait at least 24 – 48 hours to get the answer. Why? Because I’m writing this at 11pm on Thanksgiving night and i have plans to get up at 3 AM in hopes to score myself a Nintendo Wii. Yes i’m a gamer and the last time i stood in line for the Wii i was lucky enough to find out i was number 29 in line for 26 units, a fate i hope not to repeat! So look for my next post 24 hours after this one goes live (not sure when that will be since my Internet connection is flaky out here).