• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Stumped - Variable exists, then does not.

Enthusiast ,
Oct 24, 2012 Oct 24, 2012

Copy link to clipboard

Copied

Whew!  This is a new one on me!  One of those times CF simply isn't making any logical sense to how I understand it.  I've even gone through CF10 Application Server and IIS Admin service restarts and still getting the same problem.

In short, I have a template component which has a variable called rawCode.  It is the current request's generated HTML that is to be output to the buffer.  I am inside a method inside the template component, and I dump: THIS.rawCode.

Sure enough, it contains what I expect.

I then call a method from within this method (that method exists in the template component as well)

<cfinvoke component="#THIS#" method="writeOutputToBuffer">

All that method does right now is:

<cfoutput>#THIS.rawOutput#</cfoutput>

But guess what?  At that point, there's nothing!  Nothing is presented to the user.  I had it dump THIS.rawCode and BOOM, the rawCode is there and populated with what I wante returned to the user.  Has anyone seen something like this before?  I'm sure there's some rare thing I'm doing wrong here, like some recently unknown "CF10 can only support referencing a variable 20 times per request" rule or something as crazy.

Views

11.5K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Advocate , Oct 24, 2012 Oct 24, 2012

Does writeOutputToBuffer() have output="true"?

Jason

Votes

Translate

Translate
Advocate ,
Oct 25, 2012 Oct 25, 2012

Copy link to clipboard

Copied

Someone just asked me offline, because of this thread, why I thought cfinvoke was evil. I figure I would post my response here to answer for anyone else that may be interested.

Two reasons

1. It is terribly, terribly, terrible verbose. Consider these two equivilent code blocks:

<!--- non-cfinvoke version --->

<cfset myvar =  myObject.myCustomFunction(arg1=arg1, arg2=arg2)  />

<!--- cfinvoke version --->

<cfinvoke component="#myobject#" method="myCustomeFunction" returnvariable="myvar">

     <cfinvokeargument name="arg1" value="#arg1#" />

     <cfinvokeargument name="arg2" value="#arg2#" />

</cfinvoke>

This extremely simple function takes almost 4x more characters to type as a cfinvoke than otherwise. Extrapolate that to larger functions and you get an ugly, ugly, hard-to-read mess. All that code just runs together in my eyes and it's hard ot tall where the arguments are, what the return variable will be etc. The non-cfinvoke version is so much cleaner and to anyone that has programmed using any other language, it is obvious what is going on.

2. cfinvoke cannot create persistent objects

If you use cfinvoke to create an object, you cannot reuse that object. So in most cases, you're going to have to use createObject() anyway to create the object for cfinvoke to use which removes half of the once perceived benefit of cfinvoke.

Hope that clears it up,

cfinvoke is just ugly syntax. ColdFusion gets enough grief about being verbose and ugly. Let's not make it worse by using cfinvoke when there are better, easier, more useful and effective options.

Jason

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 25, 2012 Oct 25, 2012

Copy link to clipboard

Copied

I agree with everything you say.

Bear in mind, though, that it's a fairly common practice to have an init() method in a CFC these days, so one can do this:

<cfinvoke component="Foo" method="init" returnvariable="myFoo">

Still, that's a bit rubbish compared to:

<cfset myFoo = new Foo()>

There's also another reason: <cfinvoke> is a peculiarity of CFML, and will be meaningless to anyone from outwith CF.

Whereas these syntaxes (below) are going to be either familiar or easily inferable to most people coming from other popular languages:

myFoo = new Foo();

myFoo = createObject("Foo");

--

Adam

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 25, 2012 Oct 25, 2012

Copy link to clipboard

Copied

Just a little addition to Adam's points on cfinvoke. I think that Jason is being too hard on cfinvoke.

Why focus just on the invocation of methods? Take a look at cfinvoke's list of attributes. It contains additional functionality that is beyond the reach of any one single type of createobject() or <cfobject>. Also, with cfinvoke we can invoke a method stored in a dynamic variable more elegantly than with createobject, for example, like this:

<cfinvoke component="Foo" method="#someDynamicVar#" returnvariable="myFoo">

[edited emphasis: any one single type]

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Oct 25, 2012 Oct 25, 2012

Copy link to clipboard

Copied

I will agree that cfinvoke is useful for invoking methods when the methods name is stored in a variable.

I will not, however, concede that there is anything else that cfinvoke can do that createObject() cannot do more eloquently and with less code.

Jason

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation