6

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?

froadie
  • 71,770
  • 69
  • 154
  • 228

4 Answers4

8

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.

Ciaran Archer
  • 11,778
  • 9
  • 34
  • 54
4

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.

charlie arehart
  • 4,421
  • 3
  • 20
  • 18
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>.

Adam Tuttle
  • 18,859
  • 17
  • 72
  • 109
Todd Sharp
  • 2,927
  • 2
  • 17
  • 27
  • 1
    No reason to use short urls here. Updated to just point to the ultimate destination. ;) – Adam Tuttle Jan 05 '11 at 19:24
  • I copied directly from Google with all the other extraneous nonsense so I just hit the 'shorten with bit.ly' bookmarklet to make it cleaner. Thanks for updating it. – Todd Sharp Jan 05 '11 at 20:33
4

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.

James Buckingham
  • 825
  • 5
  • 13
  • 1
    -1 for "but a pro of it is you can dynamically loop over the methods within a CFC. In createobject you can't." for (var k in o) { if (isCustomFunction(o[k])) { o[k](argumentCollection = whatever); } } This will work verbatim in Railo. For Adobe CF 7-9, you need to do: var k = ''; for (k in o) { var m = o[k]; if (isCustomFunction(m)) { m(argumentCollection = whatever); } } – Olson.dev Apr 13 '12 at 19:33