Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a function from another function using the reference of object of a cfc?

Sorry about the question phrase. I couldn't find better way to describe it. But my problem is as follows:

I have 3 cfc's namely settings.cfc, prices.cfc and helpers.cfc. These cfc's extend 4th cfc controller.cfc. The helper.cfc is as follows:

<cfcomponent extends="Controller">
    <cffunction name="formatCurrency">
        <cfset formattedCurrency = 1 />    
        <cfreturn formattedCurrency>        
    </cffunction>
    <cffunction name="processTemplateVariables">
       <cfargument name="templateText" default="defaultText" >
       <cfset formatCurrency() />
       <cfreturn formattedCurrency >        
    </cffunction>
</cfcomponent>

The settings.cfc has a setApplicationVariables method which we use to set the application level variables. In this cfc, i have created an object of helpers.cfc and put that object into the application scope. The settings.cfc is as follows:

<cfcomponent extends="Controller">
   <cffunction name="setApplicationVariables">    
      <cfset application.helpers = createObject("component","controllers.Helpers") />  
   </cffunction>
</cfcomponent>

The settings.cfc gets invoked on application start which in turn creates a object of helpers.cfc and put it into the application scope.

We create a reference to the method ProcessTemplateVariables in the controller.cfc as follows:

<cfcomponent extends="Wheels">
   <cfset getFormattedCurrency = application.helpers.processTemplateVariables >
</cfcomponent>

In the prices.cfc, we use this reference to call the function processTemplateVariables, which it does. But it does not call the function formatCurrency that is called inside from the processTemplateVariables and it throws error "variable formatCurrency is undefined".

But if i use the application.helpers.processTemplateVariables(templateText="someText"), it works.
It also works, when i use cfinvoke as bellow:

<cfinvoke method="processTemplateVariables" component="controllers.helpers" templateText="someText" returnvariable="content">

The prices.cfc is as follows:

<cfcomponent extends="Controller">
    <cffunction name="index">
        <!--- does not work, throws 'the formatCurrency() variable is undefined' --->
        <cfdump var="#getFormattedCurrency("someText")#"><cfabort>
        <!--- works --->    
        <cfinvoke method="processTemplateVariables" component="controllers.helpers" templateText="someText" returnvariable="content">
        <!--- works --->
        <cfset application.helpers.processTemplateVariables("someText") />   
    </cffunction>
</cfcomponent>

I am not sure why using reference is not working. Sorry about the earlier confusion but your comments made me dig deeper and i could found out that it was reference that was culprit. Is there any way to make this work with reference, that would be cool?

like image 421
Tushar Bhaware Avatar asked Oct 19 '22 20:10

Tushar Bhaware


1 Answers

Update:

This blog entry (by Adam Cameron) has a better description. To summarize:

.. it pulls the method out of the CFC, so it will be running in the context of the calling code, not the CFC instance. Depending on the code in the method, this might or might not matter.

In your specific case it does matter. The function has a dependency on formatCurrency, which does not exist in the "context" of the calling page, and that is why you get an "undefined" error.


(From comments)

Yeah, I am pretty sure you cannot do that. Each function is compiled into an individual class: specifically a static inner class. (You can see the inner class names if you dump out the function name without parenthesis ie #application.helpers.formatCurrency#) In other words, it is disconnected from any specific instance - and by extension - the other functions.

When you create an instance of the component, all of the functions are stored its variables scope. So when you invoke "processTemplateVariables" - from within the instance - it has access to the other functions via the component's variables scope. When your code creates a reference to that function, what you are actually getting is completely disconnected from the parent instance ie application.helpers. So it won't have access to any of the other functions. Hence why you get an "undefined" error.

like image 169
Leigh Avatar answered Nov 01 '22 08:11

Leigh