In my company's code, I've often seen component files used by initializing an object of that component and calling the methods off the object. However, it seems to me somewhat more straightforward to use the cfinvoke method, especially when only using one method from the component file. What are the differences between these 2 methods of calling a component function and what are the pros/cons of each? When should I use which?
问题:
回答1:
cfinvoke can only be used in tags.
createObject can be used in both tags & cfscript and tends to be a bit slimmer / easier to read IMO.
Until recently I avoided using cfinvoke because I found it "bulky" but a pro of it is you can dynamically loop over the methods within a CFC. In createobject you can't.
So if for example I've got a CFC which has the methods - method1, method2, method3, method4. I can loop over them like so:-
<cfloop from="1" to="4" index="element">
<cfif structKeyExists(this,'getMethod#element#')>
<cfinvoke component="#this#" method="getLine#local.element#" returnVariable="methodValue"></cfinvoke>
<cfset arrayAppend(myArray,methodValue) />
</cfif>
--
Another thing to note is that some sharing hosts lock down on createobject. Mainly because of the access it gives to the underlining Java.
回答2:
One other benefit of using createObject()
is that you can chain the init()
method, e.g.
<cfset myObject = createObject("com.path.MyObject").init() />
And if your init()
returns this
you can go further and chain the method if you don't need to use the object again:
<cfset functionResults = createObject("com.path.MyObject").init().myFunction() />
It's worth pointing out that in CF 9 you can use the new (ahem) new
syntax to create objects. For example to create the same object as above and call it's init()
I can write:
<cfset myObject = new com.path.MyObject() />
It's neat and I like the option to do this. CF is moving in the right direction in my opinion with features like this.
回答3:
You've nearly answered it yourself: on the surface, one could say that if you will be calling only one method on a page, then doing in one fell swoop in CFINVOKE (which instantiates the CFC and calls the one named method) make sense. And certainly if you would call more than one method of the CFC on a page, then separating the steps makes sense (instantiate the CFC with the createobject function or cfobject tag, then invoke methods as found in that object, a pointer to the CFC), so that you don't pay that instantiation cost more than once.
But do keep in mind that if the page is called often, it may make sense also to save that result of instantiating the CFC, so that it can be reused on a subsequent request to the page. You would do that by storing it (the result of cfobject/createobject) not in a local variable but instead in a shared scope: whether server, application, or session, based on "who" would benefit from such reuse. Of course, it's then incumbent on you to programmatically handle/decide how long to save this "cached" CFC instance.
As important, when you save a CFC instance this way, you become more susceptible to the "var scope bug", which basically is that you need to be still more careful to VAR any local variables you create in the CFC. Rather than try to elaborate more on that, I'll point out a meta-resource I created on that:
http://www.carehart.org/blog/client/index.cfm/2010/3/4/resources_on_the_var_scope_problem
Hope that helps.
回答4:
Rather then rehash this discussion I'll just point you towards Google:
http://www.google.com/search?q=cfinvoke+vs+createobject
There are some subtle differences (IE: <cfinvoke>
is capable of handling dynamic method names) but essentially it just boils down to personal preference. Well, that and the fact that you can't use <cfinvoke>
via <cfscript>
.