Think of a Coldfusion Component, first introduced in Coldfusion 6, as a container, an object. Inside this object you can store related data, manage related functions, access data sources, implement business logic and more. While Coldfusion is not an Object Oriented Programming Language, using components, we can implement OO programming concepts and solve recurring problems using design patterns.

Basic object (component)

Object.cfc
view plain print about
1<cfcomponent output="false" name="Object" hint="Simple CF Object">
2
3    <cffunction name="init" access="public" output="false" returntype="Object" hint="constructor">
4        <cfreturn this />
5    </cffunction>
6
7</cfcomponent>

A Coldfusion Component is defined by the file extension CFC. It begins and is closed with the cfcomponent tag. The component can contain 1 to N functions. Note: the word "method" is often used instead of "function".

A CFC can be placed in any website accessible folder, as well as any CF Administrator defined Mapping or Custom Tag folder.

This component contains a single function, init(), which is the object's constructor.

The constructor method

In object oriented programming, a constructor is the method called when an object is created. The returntype of the constructor method is usually the name of the object.

Technically speaking, Coldfusion Components do not require and cannot specify a constructor method for a CFC. Using the init() method has become a best practice throughout the Coldfusion community.

The final line of the constructor, <cfreturn this />, returns the contents of the object to whichever process called it.

Creating an instance of Object.cfc 1.
view plain print about
1<cfset obj = createObject("component", "Object").init() />
2.
view plain print about
1<cfscript>
2obj = createObject("component", "Object").init();
3
</cfscript>
3.
view plain print about
1<cfobject component="Object" name="obj" />
2<cfset obj = obj.init() />
4.
view plain print about
1<cfinvoke component="Object" method="init" returnVariable="obj" />

The point of creating an instance of an object is to load the CFC into memory only once. In this case, all four variations of creating an instance created the variable "obj". If the object contained more functions, you would then just write

view plain print about
1<cfset obj.doSomething() />

to call the function "doSomething" from the instance of "obj" that is already in memory.

Note: The only problem with using <cfobject /> (3) to create an instance of an object is that you can't call a constructor method directly from the tag. It has to be called separately. This will only be an issue when the object's constructor has required arguments.

If you haven't created coldfusion functions before, let's discuss them next.

CFFunction Overview

Basic function attributes
view plain print about
1<cffunction name="init" access="public" output="false" returntype="Object" hint="constructor">

  • name: The name of the function. No two functions in a CFC can have the same name.
  • access:
    • A public function can be called from inside or outside the CFC.
    • private functions can only be called by other functions in the same file.
    • package access allows calls from functions in the same file and functions from other CFC files in the same folder (package).
    • remote functions are used as Web Services, but that's a discussion for another primer
  • output: since we're only working with data and logic, always set this to false
  • returntype: the datatype returned from the function - string, numeric, struct, query, component name, etc.
  • hint: The can be some simple description of the function.

While hint is optional, try to populate it with something. It helps with documentation as your object model grows.

Function arguments

In order to pass values into a function, use the cfargument tag for each value. A function can have 0 to N arguments.

Function with one argument
view plain print about
1<cffunction name="init" access="public" output="false" returntype="Object" hint="constructor">
2    <cfargument name="DSN" type="string" required="true" hint="Datasource" />
3    <cfset variables.DSN = arguments.DSN />
4    <cfreturn this />
5</cffunction>

The attributes name, type, required and hint should be apparent by now. The attribute default can be used to set a default value for a required argument when no value has been passed to it.

Passing arguments into a function

Let's say init() takes two arguments: DSN (a string) and systemDate (a date).

Function with two arguments
view plain print about
1<cffunction name="init" access="public" output="false" returntype="Object" hint="constructor">
2    <cfargument name="DSN" type="string" required="true" hint="Datasource" />
3    <cfargument name="systemDate" type="date" required="true" hint="today's date" />
4    <cfset variables.DSN = arguments.DSN />

5    <cfset variables.systemDate = arguments.systemDate />

6    <cfreturn this />
7</cffunction>

Passing arguments as a list When using a list, the arguments must be passed in the exact order that the arguments are defined. If you have 5 required arguments, but only 4 arguments, then the 5th argument will throw an error unless a default value was specified.
view plain print about
1<cfset variables.datasource = "myDSN" />
2<cfset obj = createObject("component", "Object").init( variables.datasource, now() ) />

Passing named arguments
view plain print about
1<cfset variables.datasource = "myDSN" />
2<cfset obj = createObject("component", "Object").init( DSN = variables.datasource, systemDate = now() ) />

Passing arguments using cfinvoke
view plain print about
1<cfset variables.datasource = "myDSN" />
2<cfinvoke component="Object" method="init" DSN="#variables.datasource#" systemDate="#now()#" returnVariable="obj" />

Passing arguments using an Argument Collection

An Argument Collection is a struct whose key names match the arguments in the function. Notice that rather than using a variable named "datasource", here we have to use one named "DSN".

view plain print about
1<cfset variables.foo = structNew() />
2<cfset variables.foo.DSN = "myDSN" />
3<cfset variables.foo.systemDate = now() />
4
5<cfinvoke component="Object"
6    method="init"
7    returnVariable="obj"
8    argumentcollection="#variables.foo#" />

or
view plain print about
1<cfset variables.foo = structNew() />
2<cfset variables.foo.DSN = "myDSN" />
3<cfset variables.foo.systemDate = now() />
4
5<cfset obj = createObject("component", "Object").init( argumentCollection = variables.foo ) />

Using cfscript

Defining a function with cfscript
view plain print about
1<cfscript>
2function init()
3{
4    return this;
5}
6
</cfscript>

When using cfscript there's no way to explicitly define an argument's datatype or the returntype. If you want to use cfscript in your function, I recommend you stick to using cffunction and cfargument first, then use cfscript to write the actual logic of the function.

cffunction with cfscript
view plain print about
1<cffunction name="init" access="public" output="false" returntype="Object" hint="constructor">
2    <cfargument name="DSN" type="string" required="true" hint="Datasource" />
3    <cfscript>
4        variables.DSN = arguments.DSN;
5        return this;
6    
</cfscript>
7</cffunction>

What is a Design Pattern?

Basically, a Design Pattern is a common solution to a recurring problem.

In this Object Oriented Coldfusion Primer, we'll introduce various objects and discuss what issues they address.

  • The Gateway Object
  • The Bean
  • The Data Access Object (DAO)
  • The Service Object
  • The Facade

If you want to see something covered that's not in this list, please let me know.

Return this

So far we've covered how to create a simple Coldfusion object, as well as how and why to call its constructor method. We've also covered the basics of functions (methods) and arguments.

When we create this simple Object.cfc, we're creating an instance of the object which contains a single method, init(). Before we can get into specific types of objects, there are a few more general aspects of Coldfusion Objects that need to be explored.

Next we'll go over different variable scopes as they relate to objects.