How to Invoke CFC Methods with CFML
In this tutorial, we'll learn the basics of creating and working with CFCs in CFML, their importance, and code examples so you can get started with your own custom functions quickly.
What Are CFCs?
CFCs (ColdFusion Components) are a great demonstration of the true power behind CFML and a way to separate your application logic from your interface. They're especially useful for creating reusable bits of code that you can utilize and invoke throughout your application.
CFCs use the .cfc
file extension to help differentiate from a regular .cfm
script file.
Tags for Creating CFCs
We'll explore three different tags associated while creating our CFC:
cfcomponent
- Defines the component and includes specific attributes for introspection.cffunction
- Defines a component method, or function, that you can invoke from other CFCs or CFML files.cfargument
- Defines a custom argument, or parameter, for each function.
CFC Code Example
Let's create our first CFC and walk through its structure and each of its features. Create a file called Data.cfc
and copy/paste the following code:
<cfcomponent displayName="myComp" output="false">
<cffunction name="myFunc" returnType="query" output="false">
<cfargument name="id" type="numeric" required="true">
<cfset var qryData = "">
<cfquery name="qryData" datasource="myDatasource">
SELECT *
FROM myTable
WHERE id = <cfqueryparam value="#arguments.id#" cfsqltype="cf_sql_bigint">;
</cfquery>
<cfreturn qryData>
</cffunction>
</cfcomponent>
Every CFC must start with an opening and closing cfcomponent
tag. This defines the CFC and creates an association with its included methods. The displayName
attribute is used for introspection. The output
attribute is an option boolean parameter. In this case, a value of "false" prevents unnecessary page output while processing the function.
Within each component, you can create as many functions as you'd like using the cffunction
tag. In this example, we've created a single function called "myFunc" where we'll query a hypothetical database table by returning all columns and their associated values that match a given "id". The returnType
specifies the resulting data type expected to be returned from the function call, in this case, our query results. And the optional output
parameter with a value of "false" instructions the function to refrain from returning text, including whitespace, in the result.
Within the function, you can create as many arguments as you'd like using the cfargument
tag. In this case, a numeric ID variable is required to continue processing the remainder of the function call. If the ID variable is not passed in, an error will be thrown.
Next, we have a local variable qryData
prefixed with the var
keyword, indicating that this variable can only be used inside the function where it's declared. This is important and best practice to prevent accidental variable rewriting within other CFC methods.
Finally, we use the cfquery
tag to execute our SQL call and return the resultset from the query.
Invoking CFC Methods
To invoke our CFC methods, retrieve the return data, and output the resultset to the screen, we'll explore a few different options.
The cfinvoke
tag
The first method is with the cfinvoke
tag. Here, we'll invoke a function call to our newly created component and method, and assign a return variable we can use to dump the data:
<cfinvoke component="myComp" method="myFunc" returnVariable="qryData">
<cfdump var="#qryData#">
The cfobject
tag
The second method is with the cfobject
tag. Similar to the first, we invoke our newly created component method, but instead, we create an instance of the component that we can reuse without redefining it each time. This can significantly improve processing time where you're making multiple component calls in a single page request:
<cfobject name="objComp" component="myComp">
<cfset qryData = objComp.myFunc(id = 1)>
<cfdump var="#qryData#">
<cfset qryData = objComp.myFunc(id = 2)>
<cfdump var="#qryData#">
The CreateObject()
function
The third method is very similar to the previous method, except we use the CreateObject()
function to create an instance of our component and associated methods instead of a tag.
<cfset objComp = CreateObject("component", "myComp")>
<cfset qryData = objComp.myFunc(id = 1)>
<cfdump var="#qryData#">
<cfset qryData = objComp.myFunc(id = 2)>
<cfdump var="#qryData#">
The CreateObject()
method is my preferred way of defining objects in CFML due to the flexibility it allows. Here, you're passing in two arguments to the function call. The first argument is the type of object we're creating an instance for, in this case, a component. The second argument is the name of the component, "myComp".
The one thing I'd like to note about passing in a component name is the location of the CFC file. Passing in "myComp" assumes that the component is in the same folder as the script executing the code. However, if the component file were located in a sub-directory, you would use dot notation to separate each directory name to its location:
<cfset objComp = CreateObject("component", "path.to.myComp")>
Conclusion
That's it! Components in real-world applications can be a lot more complex than this, but this basic structure should get you going in the right direction.