Using UDFs effectively

Using UDFs effectively

Many techniques help you use user-defined functions more effectively.

Using functions in ColdFusion component

In many cases, the most effective use of UDFs is within a CFC. For more information on CFCs, see Building and Using ColdFusion Components.

Using Application.cfm and function include files

Consider the following techniques for making your functions available to your ColdFusion pages:

  • If you consistently call a small number of UDFs, consider putting their definitions on the Application.cfm page.
  • If you call UDFs in only a few of your application pages, do not include their definitions in Application.cfm.
  • If you use many UDFs, place their definitions on one or more ColdFusion pages that contain only UDFs. You can include the UDF definition page in any page that calls the UDFs.
    The next section describes other techniques for making UDFs available to your ColdFusion pages.

Specifying the scope of a function

User-defined function names are essentially ColdFusion variables. ColdFusion variables are names for data. Function names are names (references) for segments of CFML code. Therefore, like variables, functions belong to scopes.

About functions and scopes

Like ColdFusion variables, UDFs exist in a scope:

  • When you define a UDF, ColdFusion puts it in the Variables scope.
  • You can assign a UDF to a scope the same way you assign a variable to a scope, by assigning the function to a name in the new scope. For example, the following line assigns the MyFunc UDF to the Request scope:

<cfset Request.MyFunc = Variables.MyFunc>

You can now use the function from any page in the Request scope by calling Request.MyFunc.

Selecting a function scope

The following table describes the advantages and disadvantages of each function scope:

Scope

Considerations

Application

Makes the function available across all invocations of the application. Access to UDFs in Application scope is multithreaded and you can execute multiple copies of the UDF at one time.

Request

Makes the function available for the life of the current HTTP request, including in all custom tags and nested custom tags. This scope is useful if a function is used in a page and in the custom tags it calls, or in nested custom tags.

Server

Makes the function available to all pages on a single server. In most cases, this scope is not a good choice because in clustered systems, it only makes the function available on a single server, and all code that uses the function must be inside a cflock block.

Session

Makes the function available to all pages during the current user session. This scope has no significant advantages over the Application scope.

Using the Request scope

You can effectively manage functions that are used in application pages and custom tags by doing the following:

  1. Define the functions on a function definitions page.

  2. On the functions page, assign the functions to the request scope.

  3. Use a  cfinclude  tag to include the function definition page on the application page, but do not include it on any custom tag pages.

  4. Always call the functions using the request scope.
    This way you only include the functions once per request and they are available throughout the life of the request. For example, create a myFuncs.cfm page that defines your functions and assigns them to the Request scope using syntax such as the following:

{ Function definition goes here }
Request.MyFunc1 = MyFunc1

The application page includes the myFuncs.cfm page:

<cfinclude template="myfuncs.cfm">

The application page and all custom tags (and nested custom tags) call the functions as follows:

Request.MyFunc1(Value1, Value2)

Using the Request scope for static variables and constants

You can partially break the rule described in the section Referencing caller variables in the Working with arguments and variables in functions. Here, the function defines variables in the Request scope. However, it is a specific solution to a specific issue, where the following circumstances exist:

  • Your function initializes a large number of variables.
  • The variables have either of the following characteristics:
    • They must be static: only the function uses them, the function can change their values, and their values must persist from one invocation of the function to the next.
    • They are named constants; that is the variable value never changes.
  • Your application page (and any custom tags) calls the function multiple times.
  • You can assure that only the function uses the variable names.
    In these circumstances, you can improve efficiency and save processing time by defining your function's variables in the Request scope, rather than the Function scope. The function tests for the Request scope variables and initializes them if they do not exist. In subsequent calls, the variables exist and the function does not reset them.
    The NumberAsString function, written by Ben Forta and available from www.cflib.org, takes advantage of this technique.

Using function names as function arguments

Because function names are ColdFusion variables, you can pass a function's name as an argument to another function. This technique allows a function to use another function as a component. For example, a calling page can call a calculation function, and pass it the name of a function that does some subroutine of the overall function. 
This way, the calling page could use a single function for different specific calculations, such as calculating different forms of interest. The initial function provides the framework, while the function whose name is passed to it can implement a specific algorithm that the calling page requires.
The following simple example shows this use. The binop function is a generalized function that takes the name of a function that performs a specific binary operation and two operands. The binop function simply calls the specified function and passes it the operands. This code defines a single operation function, the sum function. A more complete implementation would define multiple binary operations.

<cfscript> 
function binop(operation, operand1, operand2) 
{ return (operation(operand1, operand2)); } 
function sum(addend1, addend2) 
{ return addend1 + addend2;} 
x = binop(sum, 3, 5); 
writeoutput(x); 
</cfscript>

Handling query results using UDFs

When you call a UDF in the body of a tag that has a query attribute, such as a cfloop tag, any function argument that is a query column name passes a single element of the column, not the entire column. Therefore, the function must manipulate a single query element. 
For example, the following code defines a function to combine a single first name and last name to make a full name. It queries the cfdocexamples database to get the first and last names of all employees, and then it uses a cfoutput tag to loop through the query and call the function on each row in the query.

Get help faster and easier

New user?