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

Creating Objects from CFCs

Participant ,
Apr 01, 2008 Apr 01, 2008

Copy link to clipboard

Copied

I am working on creating a couple of components that will act as objects in the Application and Session scopes. I have been looking at examples online and have notices a couple of different things that I assume are accomplishing the same goal, but wanted to ask someone.

I understand that the THIS scope is used within the object to store variables. I guess my questions more along the lines of how to initialize those variables.

One method I have seen used is just by declaring at the beginning of the component (as below):
<cfcomponent>
<cfset THIS.var1="lala">
<cfset THIS.var2="toto">
<cffunction....

The other method I have seen is using the method init():
<cfcomponent>
<cffunction name="init" ...>
<cfset THIS.var1="lala">
<cfset THIS.var2="toto">
</cffunction>

I am assuming that they are accomplishing the same task.

If someone can explain the differences between these two methods and if there are benefits to either one it would be greatly appreciated. Thanks!
TOPICS
Advanced techniques

Views

1.3K

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
Contributor ,
Apr 01, 2008 Apr 01, 2008

Copy link to clipboard

Copied

I think the following link has a good sample. :)

http://cfoop.org/readArticle.cfm?aid=3

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 ,
Apr 01, 2008 Apr 01, 2008

Copy link to clipboard

Copied

jeby wrote:

> I am assuming that they are accomplishing the same task.
>
> If someone can explain the differences between these two methods and if there
> are benefits to either one it would be greatly appreciated. Thanks!

Nearly but there is a subtle difference. Code, such as these initial
variable sets inside the <cfcomponent...> block, but NOT inside a
<cfunction...> block, is a ColdFusion Component's version of a
constructor. This code is always run when a component is instantiated.
But you may notice that there is no way to pass arguments to this code
when it is run at the time of creation. The ColdFusion community has
developed the 'init' function as a defacto standard to create a pseudo
constructor to which one can pass arguments.

The init function is not a true constructor, it is not automatically
called during creation of the object, rather it must be implicitly
called by the developer. Thus in your example, the code in the
<cfcomponent...> block would automatically be run every time an object
is created. The init function would only be run when told to by the
developer during run time.

This is often done with a daisy chain command so that the actions follow
one, two. I.E. myObj =
createObject("component","path.to.my.component").init()

Again the reason for using this is to pass in arguments, so one would
usually see code like this:

<cfcomponent>
<cffunction name="init" ...>
<cfargument name="var1"...>
<cfargument name="var2"...>

<cfset THIS.var1=arguments.var1>
<cfset THIS.var2=arguments.var2>
</cffunction>
</cfcomponent>

----------

myObj = createObject("component","my.component").init("lala","toto")

PS. Also must developers would put these values into the 'VARIABLES'
scope rather then the 'THIS' scope. The 'Variables' scope is private to
the component|object, the 'This' scope, on the other hand, is public.

HTH
Ian



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 ,
Apr 01, 2008 Apr 01, 2008

Copy link to clipboard

Copied

quote:

Originally posted by: Newsgroup User
PS. Also must developers would put these values into the 'VARIABLES'
scope rather then the 'THIS' scope. The 'Variables' scope is private to
the component|object, the 'This' scope, on the other hand, is public.

HTH
Ian



Public in what way? If they are not returned by any function, how could they be accessed from the calling template?

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
Valorous Hero ,
Apr 01, 2008 Apr 01, 2008

Copy link to clipboard

Copied

quote:

Originally posted by: Dan Bracuk
Public in what way? If they are not returned by any function, how could they be accessed from the calling template?



The THIS scope is public by nature. So unlike the variables scope it can be accessed, and modified, directly by the calling template.

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
Engaged ,
Apr 01, 2008 Apr 01, 2008

Copy link to clipboard

Copied

If you have an instance of a CFC called myObj then you can access this scoped variables as public properties. So if you had a THIS scoped variable called name, you can access it like myObj.name. If they were VARIABLES scoped then these could only be accessed via method calls.

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 ,
Apr 02, 2008 Apr 02, 2008

Copy link to clipboard

Copied

Dan Bracuk wrote:
> Public in what way? If they are not returned by any function, how could they
> be accessed from the calling template?

As the others said, in a component 'this' scope variables are public by
design, 'variables' scoped variables are private. But here is a more
concrete example of the concept and consequences.

<cfcomponent>
<cfset this.foo = "George">
<cfset variables.bar = "Gracie">
</cfcomponent>

----------

<cfset myObj = createObject('component','path.to.component')>

<cfoutput>
#myObj.foo#
#myObj.bar# <!--- Exception is going to be thrown here. --->

<cfset myObj.foo="Frank">

#myObj.foo#
</cfoutput>

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
Participant ,
Apr 02, 2008 Apr 02, 2008

Copy link to clipboard

Copied

I understand the difference between the variables and this scopes now (I had previously not known the difference), but back to my original question, is it common practice to initialize variables outside of all functions such as:

<cfcomponent>

<cfset variables.var1 = 22 />
<cfset variables.var2 = "test" />

<cffunction ...>
</cffunction>
</cfcomponent>

Or, should I use an init() method and create the object calling that method as follows:

<cfcomponent>
<cffunction name=init" ...>
<cfset variables.var1 = 22 />
<cfset variables.var2 = "test" />
</cffunction>
</cffunction>

Should I get in the habit of using the init constructor?

Thanks!

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 ,
Apr 02, 2008 Apr 02, 2008

Copy link to clipboard

Copied

jeby wrote:
> is it common practice to initialize variables outside of all functions such as:

Yes, this is common.

> Or, should I use an init() method and create the object calling that method as
> follows:

This is common as well.

Which you use is up to you. My first post discussed the whys and
wherefores in more detail. But you can use either you like. Setting
variables outside of all functions will always run, but you can not pass
values into the constructor at creation time. The init() method allows
one to pass in values, but it is not automatically run during
construction and thus needs to be called by the developer explicitly.

Go with either or both; whichever works for you.

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
Participant ,
Apr 04, 2008 Apr 04, 2008

Copy link to clipboard

Copied

OK... I moved my variables to the variables scope and created getter methods now... I moved my var delcarations into an init() method.

I tried calling the method all at once using (as was described either in this thread or another one i was looking in):

<cfset Session.User = createObject('component','components.user').init() />

But when I do that I get the following results when i try to do Session.User.getUserID():

Element USER is undefined in a Java object of type class [Ljava.lang.String;.

Now, If I declare it using the following:

<cfobject component="components.user" name="Session.User" />
<cfset Session.User.init() />

All seems to be well... is there a way to do this without having to call the init constructor separately?

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
Contributor ,
Apr 04, 2008 Apr 04, 2008

Copy link to clipboard

Copied

I've got an OOP with ColdFusion Primer on my site that might help. It starts here:

Intro to Object.cfc

Can you post the code for your user.cfc? What is the returntype of your init method? It should be

<cffunction name="init" access="public" output="false" returntype="User">
<cfreturn this />
</cffunction>

This makes init() return the User object itself. If it doesn't return the object, then session.user is being defined incorrectly.

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 ,
Apr 04, 2008 Apr 04, 2008

Copy link to clipboard

Copied

jeby wrote:
>
> All seems to be well... is there a way to do this without having to call the
> init constructor separately?
>

Is your init() function returning a copy of the object? It needs to end
with a <cfreturn this> tag.

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
Contributor ,
Apr 04, 2008 Apr 04, 2008

Copy link to clipboard

Copied

LATEST
Actually there are good reasons for both methods of setting variables.

The first method, setting the variables outside of any functions, is used when there will NEVER (or very very nearly never) be a need to change them. Of course these could and should be set during the application initialization and the components just pull from there. BUT for portability you may want to put the data inside.

The init() allows you to create different instances of the same component, like maybe "product" and you pass in the specs on that instance.

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