Question

I am hoping that someone can explain this behavior, as I find it pretty aggravating. I have a parent class with an OnMissingMethod implementation to provide implicit getters/setters (old CF8 application)

if I instantiate the child class as foo and call foo.getBar() from an external file, it successfully triggers OnMissingMethod, but if within the foo class itself I call getBar() it doesn't. The only way it will trigger OnMissingMethod is if I use this.getBar() which I don't like for aesthetic and code inconsistency reasons.

tldr; here is a code example... try it yourself.

Foo.cfc

<cfcomponent output="false" extends="Parent">

        <cffunction name="init" output="false" returntype="Foo">
            <cfreturn this />
        </cffunction>

        <cffunction name="getInternalBar_workie">
            <cfreturn this.getBar() />
        </cffunction>

        <cffunction name="getInternalBar_noworkie">
            <cfreturn getBar() />
        </cffunction>

</cfcomponent>

Parent.cfc

<cfcomponent output="false">

    <cffunction name="OnMissingMethod">
        <!--- always return true for this example --->
        <cfreturn true />
    </cffunction>

</cfcomponent>

foobar.cfm

<cfset foo = CreateObject( "component", "Foo").init() />

<!--- this works --->
<cfdump var="#foo.getBar()#" /><br/>
<!--- this works --->
<cfdump var="#foo.getInternalBar_workie()#" /><br/>
<!--- this fails --->
<cfdump var="#foo.getInternalBar_noworkie()#" />

Can anyone explain why the 'this' scope must be used for OnMissingMethod to work properly when calling from the class itself? Is there a better workaround?

Was it helpful?

Solution

Thank goodness for Google. I didn't know the answer, but googled "coldfusion onmissingmethod this scope" and the first match explained your situation in one of the comments. I feel bad for reproducing Elliott's work, but it gets your question answered:

[...]

CFCs are just proxied pages. CreateObject() returns a TemplateProxy that wraps the CFPage that is your actual code.

[...]

when you call the function as "this.getFoo()" or from the outside as "myObject.getFoo()", instead what happens is that it calls a method on the TemplateProxy for invoking a method, which in turn calls the function on the proxied page.

OnMissingMethod handling exists in the invoke() function on the TemplateProxy, thus it only works from outside or through the this scope.

[...]

OTHER TIPS

This shows the difference between public members and private members. The call to getBar() isn't a shortcut for the public this.getBar(). It's a shortcut for the private variables.getBar(), which doesn't exist in Parent.cfc. The private function variables.getBar() only exists in the variables scope of Foo.cfc. Because it's a public function, it is also accessible as a public member of the entire instantiated class within the this scope. The parent can't refer to private variables inside the extended (child) object. But the parent can refer to the public members.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top