What is the difference between using cfinvoke and createObject to run a component function?
Asked Answered
B

4

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?

Bladdernut answered 5/1, 2011 at 15:22 Comment(0)
I
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.

Imperative answered 5/1, 2011 at 16:0 Comment(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); } }Creekmore
A
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.

Anarthrous answered 5/1, 2011 at 16:38 Comment(0)
S
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.

Septuplet answered 5/1, 2011 at 15:23 Comment(0)
S
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>.

Suchlike answered 5/1, 2011 at 15:54 Comment(2)
No reason to use short urls here. Updated to just point to the ultimate destination. ;)Reaper
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.Suchlike
I
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.

Imperative answered 5/1, 2011 at 16:0 Comment(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); } }Creekmore

© 2022 - 2024 — McMap. All rights reserved.