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

Could someone help me understand component extension?

Enthusiast ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

I've read a couple chapters over on component extension (use of the EXTENDS attribute in a CFCOMPONENT tag) but something isn't clicking; so I'm looking to the forums for some supplemental info that'll help me have a eureka moment and comprehend.

As a preface, I have, what I would call, an intermediate knowledge of CF (working towards advanced).  So if we can keep the explanations into as much Layman's terms as possible, that would be appreciated and most helpful.

To my knowledge, if you have a component, you can make its THIS-scope variables and its methods available to other components if those components have an EXTENDS attribute in their CFCOMPONENT tag that uses a fully-qualified dot notation path to the "extended-from" component.

I tried to put this into practice by having a master.cfc and slave.cfc  The master is located off the root in a folder called 'www'.  The slave is located off the root in at the location: 'www/app/coms'.  So in the slave.cfc component I wrote:

<cfcomponent extends="www.master" ...

Assuming that it was the same as CF starting from the root of the website and looking into the www folder and then seeing the master.cfc.

But when I have the slave component call a function that exists in the master, it says it cannot find it.  What am I not getting here?  This sounds like a POWERFUL way to share the application.cfc's THIS-scope variables, so I'd like to comprehend this ability, but there's something I'm missing it seems.

Views

2.1K

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 16, 2012 Oct 16, 2012

Aegis Kleais wrote:

But we changed it to "/www.application" and boom, it showed both the THIS scope variables set in the 'parent' and the THIS scope variables in the 'child'.

I'm surprised that works. Don't do it. That is not correct, even if it does work.

The best way to handle component FQNs is to use mappings. In your example above, create a mapping to /www.

Jason

Votes

Translate

Translate
Advocate ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

Is www part of your FQN?

When you create an instance of slave.cfc do you use the FQN www.app.coms.slave?

By the way, more appropriate names are Parent.cfc and Child.cfc. It is not really a master/slave relationship, it is a parent/child relationship. The extended CFC does not control the CFC doing the extending.

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
Enthusiast ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

Yeah, the semantics of the naming was just used in reference to one being the "extended from" (master) rather than if one had control over the other or not.

Actually, I did some local testing and a co-worker suggested that we start the EXTENDS attribute off with a forward slash (for an absolute path) and that fixed it!  All the problem stemmed from me not being familiar with ColdFusion's component searching methods.  In the example of EXTENDS="www.application" if I executed that code from "/www/app/coms" then CF would look for "/www/app/coms/www/application" first, and start traversing up the directory until it could find it.  Which is odd, cause eventually you'd think it would get to the root of the website and go into 'www/application' and find it.

But we changed it to "/www.application" and boom, it showed both the THIS scope variables set in the 'parent' and the THIS scope variables in the 'child'.

Just for clarification, too, if both components shared a similar-named function, I could call the parent by using the SUPER scope, right?

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 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

Aegis Kleais wrote:

But we changed it to "/www.application" and boom, it showed both the THIS scope variables set in the 'parent' and the THIS scope variables in the 'child'.

I'm surprised that works. Don't do it. That is not correct, even if it does work.

The best way to handle component FQNs is to use mappings. In your example above, create a mapping to /www.

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
Enthusiast ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

Oh.  Mappings.  Of course.  We have created a THIS.mappings structure, so I guess I could use one of those which already maps to the application's framework directory (which is configured in a config XML file.

Can I ask why it's not a good practice?  Nonetheless, great idea; gonna go try to implement it.

@Adam-

Cool.  I was not previously familiar with the concepts of runtime and compile time, but that makes sense now that I think about it.

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
Enthusiast ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

OK, here's the issue I'm having so far.

In the application.cfc (located at '/www/application.cfc') in the pseudo constructor, I created a THIS.mappings structure and made a key in it called '/app' which maps to 'c:\inetpub\wwwroot\localhost\www', a valid location)

Then down in the onApplicationStart() code, for S&G's, I wrote the following:

<cfdump var="#fileExists( expandPath( '/app/application.cfc' ) )" abort="1">

Since no such folder ('app') exists at the root, the only way this code would return YES/TRUE is if the THIS.mappings '/app' key worked (cause there is an application.cfc in the root's 'www' folder)

Sure enough, it says "YES" when I run the code.  So everything's good.

Well, I'm now going through code in the oAS() that instantiates componenents and stores it into the application scope.  The testing component is called 'template.cfc' (located at c:\inetpub\wwwroot\localhost\files\framework\current\coms)  In that template.cfc I set the attribute to each of the following in multiple attempts:

extends="/app.application"

extends="/app/application"

extends="app.application"

When the template.cfc is stored into the APPLICATION scope, it is put into a variable called 'application.coms.template'.  But when that component is processsed, I keep getting the error:

COULD NOT FIND THE COLDFUSION COMPONENT OR INTERFACE /app.application

I checked CF10 documentation, and it says that the EXTENDS attribute can take such a FQDN pathing... wasn't it supposed to respect values set in the THIS.mappings?

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 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

So are you still putting extends="/app.application"?  That's the part I meant not to do.  Lose the slash, it should work without it.

Having the slash there is NOT the right way to do it, even if in some situations it does work.

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
Enthusiast ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

You're correct.  I did lose the slash.  So now it's just 'app.application' (I'm assuming CF will go to the site root and look down the directory structure)  This is confirmed cause I dumped the component and sure enough in the red component table, it converted 'app.application' to 'www.application' (since '/app' is a mapping which mapps to the 'www' folder)

I think the problem I'm having here is that some of my <cfparams> in the pseudo constructor of the application.cfc are calling component methods that extend app.application in order to dynamically determine what value they should be.  I have stopped this and just hard-coded the value, and that seems to fixed it.

So much of my grief comes from the want to make this thing as dynamic as possible.  The moment I hard-coded application.cfc THIS-scope vars and it's global params, it solved a lot of that, lol.

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 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

I think the problem I'm having here is that some of my <cfparams> in the pseudo constructor of the application.cfc are calling component methods that extend app.application

So hang on.  You have this sort of thing:

Parent.cfc

Child.cfc (extends Parent.cfc)

(ignoring they're Application.cfcs for the purpose of this: it doesn't matter).

Then in your code in Parent.cfc you refer to methods in Child.cfc?

If so: don't.  A parent component should be unaware of components that inherit from it.  TBH, it should work in CF (I think?), but it's just really poor programming.

I recommend you read up on OO practices, specifically around inheritance.

--

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
Enthusiast ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

@Adam

For clarification, no I wasn't having the parent execute functions in the child.  It was the other way around.  I was wondering if you had a method with the same name in both parent.cfc and child.cfc, if you were in the child.cfc and needed to distinguish the parent's method to be called, was there a way of doing so like

<cfset NEATSCOPEHERE.nameOfMethodInParentCFC()>

Cause when I'm in a child.cfc, if there is a method called der(), I can just say:

<cfset der()>

and it runs child.cfc's der() method.  But if der() also existed in its inherited parent, would I be able to call it simply from the child?

(Sorry if I'm confusing anyone in my explanations)

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 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

That's OK,I get ya.

you're looking for the "super" keyword, eg:

// Child.cfc extends Parent.cfc

foo = bar(); // calls Child's version of bar

foo = super.bar(); // calls Parent.cfc's version of bar

Again... reading up on OO is gonna help you (both in general, and CF's implementation of it)

--

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
Enthusiast ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

LATEST

Will do.  *Bookmarks Object Oriented Programming in his CF book*

So it WAS the SUPER scope that calls up to the parent.  Cool.  Chances of my parent/child sharing the same method names is very rare, but it's nice to know I can ensure the proper method called.

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
Enthusiast ,
Oct 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

To your knowledge, is it possible to use a variable for the EXTENDS attribute?

I have tried using a string variable that used the same path, and I've tried using a variable which was a component object of the master; neither worked.

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 16, 2012 Oct 16, 2012

Copy link to clipboard

Copied

To your knowledge, is it possible to use a variable for the EXTENDS attribute?

It is not possible the inheritance info is needed at compile time, not at runtime.  So there's no such thing as "variables" at the point at which the info is needed.

--

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
Resources
Documentation