12 Replies Latest reply on Apr 4, 2008 4:37 PM by Dinghus

    Creating Objects from CFCs

    josheby Level 1
      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!
        • 1. Re: Creating Objects from CFCs
          Oğuz Demirkapı Level 1
          I think the following link has a good sample. :)

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

          • 2. Re: Creating Objects from CFCs
            Level 7
            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



            • 3. Re: Creating Objects from CFCs
              Dan Bracuk Level 5
              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?
              • 4. Re: Creating Objects from CFCs
                -==cfSearching==- Level 4
                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.

                • 5. Re: Creating Objects from CFCs
                  Stressed_Simon Level 1
                  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.
                  • 6. Re: Creating Objects from CFCs
                    Level 7
                    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>
                    • 7. Re: Creating Objects from CFCs
                      josheby Level 1
                      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!
                      • 8. Re: Creating Objects from CFCs
                        Level 7
                        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.

                        • 9. Re: Creating Objects from CFCs
                          josheby Level 1
                          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?
                          • 10. Re: Creating Objects from CFCs
                            Level 7
                            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.

                            • 11. Re: Creating Objects from CFCs
                              iKnowKungFoo Level 1
                              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.
                              • 12. Re: Creating Objects from CFCs
                                Dinghus Level 1
                                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.