I test the use of access="package" in a cfc function and it doesn't work, although I do exactly what the documentation says. It says that
1) cfcs in the same folder are considered a package and
2) a func having access="package" can be accessed by the functions of the all the other components of the same package (folder).
Please see the simple code below. All 3 files are in the same folder.
When I call index.cfm I get the message "Variable CFC2FUNC is undefined"
<!--- index.cfm --->
<!--- cfc1.cfc --->
<!--- cfc2.cfc --->
What is not correct in the code above?
Thanks in advance for your help
Copy link to clipboard
You've misconstrued how things work there, but you're very close. You still need to create an instance of cfc2 (in cfc1) in order to call a method in it from within cfc1 (or from within any cfml template).
To be clear, the access control doesn't change HOW you call methods, only WHO (what template) can call it, once the cfc is instantiated. With public, any can; with private, no other can; with package, others can but only if in the same package/folder; while remote is like public but the method can be called from outside of cfml.
In my first writing of this, I mistakenly typed public in the 2nd paragraph where I clearly meant package, while distinguishing the 4 types. I've since corrected that.
thank you for your reply. I guess your suggestion is the one below
<!--- cfc1.cfc --->
I did it and it works. I thought that as "extends=.." connects two CFCs without making any instance in one of another, in the same way acess="package" would connect CFCs of the same folder without needing instance.
Thank you very much
Glad to have helped. And there are indeed many ways to have instantiated the cfc of course, and whether in that pseudo-constructor of the calling cfc or within the method making the call. I wasn't recommending any particular way or place, just that it would need to be done somehow. 🙂
Finally, you somehow marked as " the answer" my second reply--which merely pointed out a mistake in my first. I have swapped those as "the answer" for the sake of future readers.
<!--- cfc1.cfc ---><cfcomponent><cfobject name="oCFC2" component="CFC2"><cffunction name="cfc1func" access="public" returntype="string"><cfreturn oCFC2.cfc2func()></cffunction></cfcomponent>
That works, of course. But, as Charlie has hinted, there are at least 3 caveats:
<cffunction name="cfc1func" access="public" returntype="string"> <!--- The instance oCFC2 is only available within this function. The object no longer exists after cfc1func returns. Advantages: Loose coupling; Avoidance of thread contention; Code that is less complex, hence easier to maintain ---> <cfset local.oCFC2=""> <cfobject name="oCFC2" component="CFC2"> <cfset local.ret = oCFC2.cfc2func()> <cfreturn ret> </cffunction>
Charlie has given you one suggestion for a solution. Namely, to create an instance of cfc2, and use it to make the cfc2func() call. Pretty much as you've done in index.cfm.
A second suggestion is to use the current code, but with cfc1 extending cfc2. That is:
<!--- cfc1.cfc ---> <cfcomponent extends="cfc2"> <cffunction name="cfc1func" access="public" returntype="string"> <cfset local.ret = cfc2func()> <cfreturn Ret> </cffunction> </cfcomponent>
However, you shouldn't do that just for convenience. It is poor design to have ArbitraryComponent.cfc to extend AnotherArbitraryComponent.cfc.
There should be a reason in your design for using extension. Examples:
thank you for your reply. Your comment is alsolutely right. Extending whatever from wherever to whatever else wherever it is, is poor design and in case of middle and up size projects it leads to a mess "OOP".