A reader just sent this in:
I'm getting a bit confused as the difference in variables used in components. This, Variable, Var, Caller, etc....Can you clear the fog in my head for me?
I talked a bit about scopes in CFCs before, specifically an entry on November 25th about Variables versus Var in a CFC. But now is probably a good time to write out a good list:
Scopes in a CFC
Scope | Purpose/How it Works/Etc |
---|---|
Variables | The variables scope is available to the entire CFC. A value set in the variables scope in one method, or in the constructor, will be available to any other method, or the constructor, in the CFC. I typically use variables in much the same way I use Application variables in an site. |
This | The This scope acts like the Variables scope in that it is "global" to the CFC. However, it is also accessible outside the CFC. So if foo is an instance of the CFC, and you do: foo.name = "Rabid" outside of the CFC, then you have just creating a key called "name" in the This scope with the value of "Rabid." You can also cfoutput the value of foo.name. Because of this accessibility, many folks recommend against using the This scope, and instead suggest relying on methods to set data (or get data) inside the CFC. These methods then write to the Variables scope.
To repeat: |
Var | Var scoped variables exist only for the duration of the method. You must use the var scope for any variable that should exist only inside the method, like query names, loop iterators, etc. Sorry to "shout" but the lack of var scoping is one of the trickiest things to debug when things go wrong. Unlike other scope, you do not prefix the scope name in front of the variable. |
Arguments | The arguments scope consists of every argument passed to the method. So if the calling code did foo(name="King Camden"), then the foo method will have a variable called arguments.name. |
Form, URL, Application, Session, Server, CGI, Client, Request, Cookie | These scopes act exactly as they do anywhere else. In general you should not use these scopes inside a CFC. When you do you are making your CFCs less portable between applications. |
Caller, Attributes | Caller and Attributes do not exist inside a CFC. They should only be used inside custom tags. |
I think I covered everything here. Anyone think we need a CFC "Cheat Sheet" PDF?
Editors Note: I'm getting some good feedback on this entry. I'll be editing the entry from time to time instead of just posting comments, so revisit the entry.
Archived Comments
That is quite possibly the clearest, most consise definitions of these items/concepts I have read.
Watch that traffic come in, Ray. This is hella useful!
I've pointed back to it from acid.
And yes, PDF with this and other cogent information - with enough work (I'm happy to help), we could come up with a really useful CFC guide.
Don't forget Client, Cookies and Request.
http://www.depressedpress.c... has a good write-up on scoping.
Thanks for this Ray.
It confirms what I'd suspected, but it's nice to see it laid out in a single place.
For those who want a Java parallel, you might add:
variables = protected
this = public
And Java Private doesn't exist in a CFC.
Bow down to King Camden he's Rabid with variable scopes!
P.Senn, added.
Great list Ray! Quick follow up question: When/Why would you use a contructor function? Or, what about accessor functions?
MikeD - I'll answer in a separate blog post later today.
this is a great post... but now I am confused about using "This" scope. I use it all the time (inside a cfc) and I have a separate instance for each time certain methods are called so that each user can work on a separate instance of a "system" or a "worklog" or an "employee" I pretty much picked up this method from the ColdfusionMX Bible. Create an instance, initialize it, use a form to make changes, then call the "Set" methods to save the form data to the instance, then call the commit method to save the instance to the database. Have I been doing it all wrong?
Michael,
It sounds like you're implementing things, for the most part, the way I would. The difference between "this" and "Variables" can be explained like this:
<cfcomponent>
<cfscript>
this.MyVar1 = "test";
variables.MyVar2 = "test 2";
</cfscript>
</cfcomponent>
now, in a page, you create the component instance:
<cfscript>
MyComponent = CreateObject('component','whatever');
</cfscript>
This is perfectly valid, as variables in the 'this' scope are public:
<cfoutput>
#MyComponent.MyVar1#
</cfoutput>
Your can set the value like this:
<cfset MyComponent.MyVar1 = "">
which completely bypasses your set method. In some cases, that could (potentially) cause problems in your compoment.
This, however, will cause errors:
<cfoutput>
#MyComponent.MyVar2#
</cfoutput>
Because the "MyVar2" is not public, and cannot be accessed directly outside of the component.
Does that help explain?
Ray,
How about a "My Quick Refs" pod and slap tables like this into it so that they stay easily accessible over time.
Wiggy
Chris - that is freaky. That is exactly what I was going to do. I'm also going to write a cheat sheet for CF Regex, as I always forget things like how to do non-greedy regex.
Jeff, are you saying that using the This scope is bad form because your component methods can be bypassed and you "should" be forcing everything to go through the component methods?
oops, second part Jeff:
or are you saying that you might inadvertantly clobber a variable you didn't mean to causing a "difficult-to-diagnose" problem?
so Ray, the order of privacy of variables in a cfc is:
Arguments: only available within the method
Var: only available within the method
Variables: available to all methods but only in the same cfc
This: available to all methods, cfc, and all other pages.
Yeah. By the way - I know fdolks may be a bit surprised by the comments layout. Yes - I am working on things and tweaking layout here and there.
I'm not saying that the "This" scope is bad form. It really depends what you want to do.
I prefer to keep my instance variables in a CFC private (in the variables scope), and then provide an interface for API (AKA List of Methods) for accessing this the information. This is what encapsulation is all about.
I don't think I explicitly said "you might inadvertently clobber a variable in the this scope and cause a difficult to diagnose problem" however I do believe that is the case.
Ray, re: cheatsheet for RegEx... Earlier in the day I printed out Pete Freitag's regex thingy:
http://www.petefreitag.com/...
great article from Dec. 2003, but maybe nothing's changed since then.
I was thinking something more simpler - basically ripping off livedocs's various tables of characters ($ == ...) into one page.
Would it be possible to give an example of encapsulation, with a CFC - or a a walk through, just no code.
I'm not quite sure how to give an example of encapsulation without writing a book. These two articles I wrote for CFDJ might help:
http://coldfusion.sys-con.c... (The concepts behind CFCs)
http://coldfusion.sys-con.c... (A CFC example)
One useful trick I've picked up somewhere for var-scoping variables:
<CFSET VAR local = StructNew()>
Everything prefixed with "local." is now var scoped. Very easy for iterator vars and queries one tends to overlook:
<CFLOOP index="local.i" ..>
<CFQUERY name="local.q" ..>
It just doesn't work with Query of Queries, the following throws an error:
<CFQUERY name="local.q2" dbtype="query">
SELECT * FROM Local.q
</CFQUERY>
Seemingly QoQ only works on hard defined scopes such as Caller, Variables, etc.
I'm hoping someone will actually see this as I'm having difficulty understanding the session scope from the cfc's perspective.
I have a site that has a cart.cfc with setters and getters for various functions. The access of this cfc is set to package and I'm using a facade cfc to call cart.cfc's various methods.
Within this cfc I set a structure called session.cart. All works well from coldfusion, I can add, remove, etc items from that structure.
Enter Remoting: When I call the facade (or the cart.cfc's) methods from remoting, it errors saying that the session variable is undefined.
I was of the understanding that the facade cfc could call the "internal" cfc and scopes such as application and session would persist. Is there anyone out there that has tackled this issue and can give me advice?
Extra Site Info:
Fusebox 4.1
CFMX7 on Linux with Apache-2.0.54
J2EE sessions enabled
Thanks in Advance!
Joel