Create a tellTime.cfc file with the following code:
You use the cfcomponent and cffunction tags to create ColdFusion components. By itself, the cffunction tag does not provide functionality. The cfcomponent tag provides an envelope that describes the functionality that you build in CFML and enclose in cffunction tags. The following example shows the skeleton of a component with two methods:
<cfcomponent> <cffunction name="firstMethod"> <!--- CFML code for this method goes here. ---> </cffunction> <cffunction name="secondMethod"> <!--- CFML code for this method goes here. ---> </cffunction> </cfcomponent>
Defining component methods
You define component methods using cffunction tags. The following example defines a CFC that contains two methods, getall and getsalary :
<cfcomponent> <cffunction name="getall" output="false" returntype="query"> <cfset var queryall=""> <cfquery name="queryall" datasource="cfdocexamples"> SELECT * FROM EMPLOYEE </cfquery> <cfreturn queryall> </cffunction> <cffunction name="getsalary" output="false"> <cfset var getNamesandSalary=""> <cfquery name="getNamesandSalary" datasource="cfdocexamples"> SELECT FirstName, LastName, Salary FROM EMPLOYEE </cfquery> <cfreturn getNamesandSalary> </cffunction> </cfcomponent>
Because component methods are ColdFusion functions, most of their features and coding techniques are identical to those of user-defined functions. For more information on using the cffunction tag to create functions, see Writing and Calling User-Defined Functions. Like other ColdFusion functions, CFC methods can display information directly by generating output, or can return a value to the code or client that invoked the method.
You use the following cffunction tag attributes only for CFCs:
- The displayname and hint attributes, which document the CFC; for more information, see Documenting CFCs in Building ColdFusion components.
- The access attribute, which controls access to the CFC; for more information, see Using access security in Using CFCs effectively.
For detailed reference information on the cffunction tag, see the CFML Reference.
Defining CFCs with related methods
When defining CFCs, it is good programming practice to organize related methods in one CFC. For example, you could place all methods that perform operations related to a user, such as addUser, editUser, and storeUserPreferences, in one CFC. You can group related mathematical functions into one CFC. A CFC can also contain all the methods and properties necessary for a shopping cart. The following CFC contains two cffunction tags that define two component methods, getEmp and getDept. When invoked, the component methods query the ExampleApps database. The cfreturn tag returns the query results to the client, or page, where the method was invoked.
<cfcomponent> <cffunction name="getEmp"> <cfset var empQuery=""> <cfquery name="empQuery" datasource="cfdocexamples" dbtype="ODBC"> SELECT FIRSTNAME, LASTNAME, EMAIL FROM tblEmployees </cfquery> <cfreturn empQuery> </cffunction> <cffunction name="getDept"> <cfset var deptQuery=""> <cfquery name="deptQuery" datasource="cfdocexamples" dbtype="ODBC"> SELECT * FROM tblDepartments </cfquery> <cfreturn deptQuery> </cffunction> </cfcomponent>
Placing executable code in a separate file
You can place executable code in a separate file from the main component definition page. By placing the method execution code in a separate file, you can separate property initialization code, meta information, and the method definition shell from the executable method definition code. This technique lets you modularize your code and helps prevent CFML pages from getting too long and complex.
To separate the component method code, use a cfinclude tag on the component definition page to call the page that contains the component method code.
If your method takes arguments or returns data to the page that invokes it, the cfargument tag and the cfreturn tag must be on the component definition page, not on the included page.
Create a component method by using the cfinclude tag
-
<cfcomponent> <cffunction name="getUTCTime"> <cfinclude template="getUTCTime.cfm"> <cfreturn utcStruct.Hour & ":" & utcStruct.Minute> </cffunction> </cfcomponent>
-
Create a ColdFusion page with the following code, and save it as getUTCTime.cfm in the same directory as tellTime.cfc:
<cfscript> serverTime=now(); utcTime=GetTimeZoneInfo(); utcStruct=structNew(); utcStruct.Hour=DatePart("h", serverTime); utcStruct.Minute=DatePart("n", serverTime); utcStruct.Hour=utcStruct.Hour + utcTime.utcHourOffSet; utcStruct.Minute=utcStruct.Minute + utcTime.utcMinuteOffSet; if (utcStruct.Minute LT 10) utcStruct.Minute = "0" & utcStruct.Minute; </cfscript>
In the example, the getUTCTime method definition calls the getUTCTime . cfm file with the cfinclude tag. The getUTCTime .cfm code calculates the UTC time representation of the current time and populates a structure with hour and minute values. The method in tellTime . cfc then uses the information in the structure to return the current UTC time as a string to the calling page. The included page must not include a cfreturn statement.
Initializing instance data
Some components have instance data, which is data that persists as long as the component instance exists. For example, a shopping cart component can have instance data that includes the IDs and quantities of items that the user places in the shopping cart. Instance data is often shared by several methods that can create, delete, or modify the data.
You can refer to instance data of a CFC only if you create an instance of the CFC. From inside the CFC, you refer to instance data of the CFC using the this prefix, for example this.firstvariable. From the calling page, you refer to instance data using dot notation, including the name of the instance of the component and the name of the instance data, as in objectname .ivarname. Components whose methods you invoke without first instantiating the component do not typically have instance data.
You initialize instance data at the top of the component definition, before the method definitions. ColdFusion executes this code when it instantiates the component; for example, when a cfobject tag creates the component instance. Because this code executes only when the instance is created and it typically "constructs" properties of the component, instance data initialization code is sometimes called constructor code.
You can use any CFML tag or function in constructor code, and the code can perform any ColdFusion processing, such as querying a database or data validation and manipulation. If one component extends another, the parent component's constructor code executes before the child component's constructor code.
ColdFusion does not require you to place the initialization code at the top of the component definition; however, it is good programming practice to do so.
The following example shows constructor code for a shopping cart CFC:
<cfcomponent> <!--- Initialize the array for the cart item IDs and quantities. ---> <cfset This.CartData = ArrayNew(2)> <!--- The following variable has the ID of the "Special Deal" product for this session. ---> <cfset This.Special_ID = RandRange(1, 999)>
For information on scopes, see The This scope and The Variables scope.
A useful technique is to define a method named init(), which initializes an instance of a CFC, acting as a constructor. The init() method can initialize constants and return an instance of the component to the calling page. The following code illustrates an example of an init() method:
<cfcomponent displayname="shoppingCart"> <cffunction name="init" access="public" output="no" returntype="shoppingCart"> <cfargument name="shoppingCartID" type="UUID" required="yes"> <cfset variables.shoppingCartID = arguments.shoppingCartID> <cfreturn this> </cffunction> <!--- Additional methods go here. ---> </cfcomponent>
In this example, the init() method uses the variables scope to make the shopping cart ID available anywhere in the CFC. For more information about scope , see CFC variables and scope.
Defining and using method parameters
You pass data to a method by using parameters. To define a component method parameter, use the cfargument tag in the cffunction tag body. To define multiple parameters, use multiple cfargument tags. The tag names a parameter and lets you specify the following:
- Whether the parameter is required
- The type of data that is required
- A default argument value
- Display name and hint metadata for CFC introspection
You can create CFC methods that do not use cfargument tags, for example, if you use positional parameters in your methods. However, most CFC methods use the cfargument tag.
Example: convertTemp.cfc
The convertTemp.cfc file consists of the following:
<cfcomponent> <!--- Celsius to Fahrenheit conversion method. ---> <cffunction name="ctof" output="false"> <cfargument name="temp" required="yes" type="numeric"> <cfreturn ((temp*9)/5)+32> </cffunction> <!--- Fahrenheit to Celsius conversion method. ---> <cffunction name="ftoc" output="false"> <cfargument name="temp" required="yes" type="numeric"> <cfreturn ((temp-32)*5/9)> </cffunction> </cfcomponent>
Reviewing the code
The convertTemp CFC contains two methods that convert temperature. The following table describes the code and its function:
Code |
Description |
---|---|
<cfcomponent> |
Defines the component. |
<cffunction name="ctof" output="false"> |
Defines the ctof method.Indicates that this method does not display output. |
<cfargument name="temp" required="yes" type="numeric"> |
Creates the temp parameter of the ctof method. Indicates that it is required and that the expected value is numeric. |
<cfreturn ((temp*9)/5)+32> |
Defines the value that the method returns. |
</cffunction> |
Ends the method definition. |
<cffunction name="ftoc" output="false"> |
Defines the ftoc method.Indicates that this method does not display output. |
<cfargument name="temp" required="yes" type="numeric"> |
Creates the temp parameter of the ftoc method. Indicates that it is required and that the expected value is numeric. |
<cfreturn ((temp-32)*5/9)> |
Defines the value that the method returns. |
</cffunction> |
Ends the method definition. |
</cfcomponent> |
Ends the component definition. |
Example: tempConversion.cfm
The ColdFusion page tempConversion.cfm is an HTML form in which the user enters the temperature to convert, and selects the type of conversion to perform. When the user clicks the Submit button, ColdFusion performs the actions on the processForm.cfm page. The file tempConversion.cfm, which is in the same directory as convertTemp.cfc, consists of the following:
<cfform action="processForm.cfm" method="POST"> Enter the temperature: <input name="temperature" type="text"><br> <br> Select the type of conversion:<br> <select name="conversionType"> <option value="CtoF">Celsius to Farenheit</option> <option value="FtoC">Farenheit to Celsius</option> </select><br><br> <input name="submitform" type="submit" value="Submit"> </cfform>
Example: processForm.cfm
The ColdFusion page processForm.cfm calls the appropriate component method, based on what the user entered in the form on the tempConversion.cfm page. Place it in the same directory as convertTemp.cfc.
<cfif #form.conversionType# is "CtoF"> <cfinvoke component="convertTemp" method="ctof" returnvariable="newtemp" temp=#form.temperature#> <cfoutput>#form.temperature# degrees Celsius is #newtemp# degrees Farenheit.</cfoutput> <cfelseif #form.conversionType# is "FtoC"> <cfinvoke component="convertTemp" method="ftoc" returnvariable="newtemp" temp=#form.temperature#> <cfoutput>#form.temperature# degrees Fahrenheit is #newtemp# degrees Celsius.</cfoutput> </cfif>
Reviewing the code
The file processForm.cfm invokes the appropriate component method. The following table describes the code and its function:
Code |
Description |
---|---|
<cfif form.conversionType is "CtoF"> |
Executes the code in the cfif block if the user selected Celsius to Fahrenheit as the conversion type in the form on the tempConversion.cfm page. |
<cfinvoke component="convertTemp" method="ctof" returnvariable="newtemp" arguments.temp="#form.temperature#"> |
Invokes the ctof method of the convertTemp component, without creating an instance of the convertTemp component. Specifies newtemp as the result variable for the method. Assigns the temperature value that the user entered in the form to the variable temp, which is specified in the cfargument tag of the ctof method. When invoking the ctof method, the temp variable is assigned to the Arguments scope. For more information about variables and scope, see CFC variables and scope. |
<cfoutput>#form.temperature# degrees Celsius is #newtemp#}}b{{degrees Fahrenheit.</cfoutput> |
Displays the temperature that the user entered in the form, the text "degrees Celsius is," the new temperature value that results from the ctof method, and the text "degrees Fahrenheit." |
<cfelseif #form.conversionType# is "FtoC"> |
Executes the code in the cfelseif block if the user selected Fahrenheit to Celsius as the conversion type in the form on the tempConversion.cfm page. |
<cfinvoke component="converttemp" method="ftoc" returnvariable="newtemp" temp=#form.temperature#> |
Invokes the ftoc method of the convertTemp component, without creating an instance of the convertTemp component. Specifies newtemp as the result variable for the method. Assigns the temperature value that the user entered in the form to the variable temp, which is specified in the cfargument tag of the ftoc method. When invoking the ftoc method, the temp variable is assigned to the Arguments scope. For more information about variables and scope, see CFC variables and scope. |
<cfoutput>#form.temperature# degrees Fahrenheit is #newtemp# degrees Celsius.</cfoutput> |
Displays the temperature that the user entered in the form, the text "degrees Fahrenheit is," the new temperature value that results from the ftoc method, and the text "degrees Celsius." |
</cfif> |
Closes the cfif block. |
To run the example, display the tempConversion . cfm page in your browser. When you enter a value in the text box of the form, the value is stored in the form.temperature variable. Processing is then performed on the processForm . cfm page, which refers to the value as form.temperature. When you invoke either method, the cfinvoke tag assigns the value form . temperature to temp; temp is the argument specified in the cfargument tag of the appropriate method. The appropriate method in the convertTemp component performs the necessary calculations and returns the new value as newtemp .For detailed reference information on the cfargument tag, see the CFML Reference.To access the parameter values in the component method definition, use structure- or array-like notation with the Arguments scope. The following example refers to the lastName argument as Arguments.lastname; it could also refer to it as Arguments1. In addition, you can access arguments directly using number (#) signs, such as #lastname#; however, it is better programming practice to identify the scope (for example, #Arguments.lastname#). Also, you can use Array- or structure-like notation, which lets you loop over multiple parameters. For more information on the Arguments scope, see The Arguments scope in CFC variables and scope.
Define parameters in the component method definition
Create a component with the following contents, and save it as corpQuery.cfc in a directory under your web root directory:
<cfcomponent> <cffunction name="getEmp"> <cfargument name="lastName" type="string" required="true" hint="Employee last name"> <cfset var empQuery=""> <cfquery name="empQuery" datasource="cfdocexamples"> SELECT LASTNAME, FIRSTNAME, EMAIL FROM tblEmployees WHERE LASTNAME LIKE '#Arguments.lastName#' </cfquery> <!--- Use cfdump for debugging purposes. ---> <cfdump var=#empQuery#> </cffunction> <cffunction name="getCat" hint="Get items below specified cost"> <cfargument name="cost" type="numeric" required="true"> <cfset var catQuery=""> <cfquery name="catQuery" datasource="cfdocexamples"> SELECT ItemName, ItemDescription, ItemCost FROM tblItems WHERE ItemCost <= #Arguments.cost# </cfquery> <!--- Use cfdump for debugging purposes. ---> <cfdump var=#catQuery#> </cffunction> </cfcomponent>
In the example, the cfargument attributes specify the following:
- The name attributes define the parameter names.
- The type attribute for the lastName argument specifies that the parameter must be a text string. The type attribute for the cost argument specifies that the parameter must be a numeric value. These attributes validate the data before it is submitted to the database.
- The required attributes indicate that the parameters are required, if not, ColdFusion throws an exception.
- The Arguments scope provides access to the parameter values.
Providing results
ColdFusion components can provide information in the following ways:
- They can generate output that is displayed on the calling page.
- They can return a variable.
You can use either technique, or a combination of both, in your applications. The best technique to use depends on your application's needs and your coding methodologies. For example, many CFC methods that perform business logic return the results as a variable, and many CFC methods that display output directly are designed as modular units for generating output, and do not do business logic.
Displaying output
If you do not specifically suppress output, any text, HTML code, or output that CFML tags generate inside your method gets returned as generated output to the client that calls the component method. If the client is a web browser, it displays these results. For example, the following getLocalTime1 component method shows the local time directly on the page that invokes the method:
<cfcomponent> <cffunction name="getLocalTime1"> <cfoutput>#TimeFormat(now())#</cfoutput> </cffunction> </cfcomponent>
Component methods that are called by using Flash Remoting or as web services cannot use this method to provide results.
Returning a results variable
In the component method definition, you use the cfreturn tag to return the results to the client as variable data. For example, the following getLocalTime2 component method returns the local time as a variable to the ColdFusion page or other client that invokes the method:
<cfcomponent> <cffunction name="getLocalTime"> <cfreturn TimeFormat(now())> </cffunction> </cfcomponent>
The ColdFusion page or other client, such as a Flash application, that receives the result then uses the variable data as appropriate.
If a CFC is invoked using a URL or by submitting a form, ColdFusion returns the variable as a WDDX packet. A CFC that is invoked by Flash Remoting, or any other instance of a CFC, must not return the This scope.
You can return values of all data types, including strings, integers, arrays, structures, and instances of CFCs. The cfreturn tag returns a single variable, as does the return CFScript statement. Therefore, if you want to return more than one result value at a time, use a structure. If you do not want to display output in a method, use output="false" in the cffunction tag.
For more information on using the cfreturn tag, see the CFML Reference.
Documenting CFCs
ColdFusion provides several ways to include documentation about your CFCs in your component definitions. The documentation is available when you use introspection to display information about the CFC or call the GetMetadata or GetComponentMetaData function to get the component's metadata. You can use the following tools for documenting CFCs:
- The displayname and hint attributes
- User-defined metadata attributes
- The cfproperty tag
For information on displaying the information, see Using introspection to get information about components in Using CFCs effectively.
The displayname and hint attributes
The cfcomponent , cffunction , cfargument , and cfproperty tags have displayname and hint attributes.
The displayname attribute lets you provide a more descriptive name for a component, attribute, method, or property. When you use introspection, this attribute appears in parentheses next to the component or method name, or on the parameter information line.
You use the hint attribute for longer descriptions of the component, method, or argument. In the introspection display, this attribute appears on a separate line or on several lines of the component or method description, and at the end of the argument description.
Metadata attributes
You can include arbitrary metadata information as attributes of the cfcomponent, cffunction, cfargument, and cfproperty tags. To create a metadata attribute, specify the metadata attribute name and its value. For example, in the following cfcomponent tag, the Author attribute is a metadata attribute. This attribute is not used as a function parameter; instead, it indicates who wrote this CFC.
<cfcomponent name="makeForm" Author="Bean Lapin">
Metadata attributes are not used by ColdFusion for processing; they also do not appear in standard ColdFusion introspection displays; however, you can access and display them by using the GetMetaData or GetComponentMetaData function to get the metadata. Each attribute name is a key in the metadata structure of the CFC element.
Metadata attributes are used for more than documentation. Your application can use the GetMetadata function to get the metadata attributes for a component instance, or the GetComponentMetaData function to get the metadata for an interface or component that you have not yet instantiated. You can then act based on the values. For example, a mathCFC component could have the following cfcomponent tag:
<cfcomponent displayname="Math Functions" MetaType="Float">
In this case, a ColdFusion page with the following code sets the MetaTypeInfo variable to Float:
<cfobject component="mathCFC" name="MathFuncs"> <cfset MetaTypeInfo=GetMetadata(MathFuncs).MetaType>
All metadata values are replaced by strings in the metadata structure returned from the GetMetadata function. Because of this, do not use expressions in custom metadata attributes.
The cfproperty tag
The cfproperty tag is used to create complex data types with WSDL descriptors and for component property documentation, as follows:
- It can create complex data types with WSDL descriptions for ColdFusion web services. For more information, see Using ColdFusion components to define data types for web services in Publishing web services.
- It can provide documentation of component properties in the ColdFusion introspection output. The introspection information includes the values of the standard cfproperty tag attributes.
The cfproperty tag does not create a variable or assign it a value. It is used for information purposes only. You use a cfset tag, or CFScript assignment statement, to create the property and set its value.
Saving and naming ColdFusion components
The following table lists the locations in which you can save component files and how they can be accessed from each location:
|
URL |
Form |
Flash Remoting |
Web services |
ColdFusion page |
---|---|---|---|---|---|
Current directory |
N/A |
Yes |
N/A |
N/A |
Yes |
Web root |
Yes |
Yes |
Yes |
Yes |
Yes |
ColdFusion mappings |
No |
No |
No |
No |
Yes |
Custom tag roots |
No |
No |
No |
No |
Yes |
ColdFusion mappings and custom tag roots can exist within the web root. If so, they are accessible to remote requests, including URL, form, Flash Remoting, and web services invocation.
When you store components in the same directory, they are members of a component package. You can group related CFCs into packages. Your application can refer to any component in a directory specifically by using a qualified component name that starts with a subdirectory of one of the accessible directories and uses a period to delimit each directory in the path to the directory that contains the component. For example, the following example is a qualified name of a component named price:
catalog.product.price
In this example, the price. cfc file must be in the catalog\product subdirectory of a directory that ColdFusion searches for components, as listed in the preceding table. When you refer to a component using the qualified name, ColdFusion looks for the component in the order described in Specifying the CFC location in Using ColdFusion components-Developing guide.
Establishing a descriptive naming convention is a good practice, especially if you plan to install the components as part of a packaged application.
Associative Array Notation
Associative Array Notation is a way to invoke a method with parameters on Objects. ColdFusion already supported invocation of functions on Objects using dot notation.
The following snippet was already supported in earlier versions.
<cfscript> obj = { testFunc = function(value){ writeOutput("Function Definition inside an Object with parameter " & value); } }; obj.testFunc("Param"); </cfscript>
However a complex object can also be invoked using Array notation. So the following snippet displays the behavior.
Syntax
Object[MethodName](Params)
file.cfc
<cfscript> obj = { testFunc = function(value){ writeOutput("Function Definition inside an Object with parameter " & value); } }; funcName = 'testFunc'; obj.testFunc("Param"); writeOutput("<br>"); obj['testFunc']("Param"); writeOutput("<br>"); obj[funcName]("Param"); </cfscript>