Welcome!

You will be redirected in 30 seconds or close now.

ColdFusion Authors: Yakov Fain, Jeremy Geelan, Maureen O'Gara, Nancy Y. Nee, Tad Anderson

Related Topics: ColdFusion

ColdFusion: Article

Creating and Using User-Defined Functions

A step-by-step guide

An old friend, whom I hadn't seen in over eight years, recently brought an eBay auction to my attention. After some rough times, someone was selling everything he owned so he could start his life completely from scratch. The seller was located in my home state (Connecticut), was a programmer computer-geek, and had long hair. "Jeff, is this you?" was the body of the e-mail.

Of course, it wasn't, but the auction reminded me that sometimes it's better to start from scratch than to try to fix what you have.

I was thinking of rebuilding some of my older sites. These sites were built while CF5 was still in development and made very little use of user-defined functions (UDFs). ColdFusion Components were only a pipe dream at that time. Given the advent of these two features, it would be more efficient for me to rebuild these sites by starting from scratch than it would be to try to continue to modify the code base as is. This month I'm going to talk about user-defined functions, and next month I'll go into ColdFusion Components.

What Is a User-Defined Function?
Before going further, you'll need to understand what a user-defined function is. In simplest terms, a UDF is a way to assign a name to a chunk of code. When you use that name, ColdFusion will know to execute its associated code. Functions can accept arguments, and they should always return a value (although it is possible to write a UDF that doesn't return anything). UDFs operate in the same manner as built-in functions, except that you must provide the code behind the function.

If you find that you are using a similar block of code many times over in your application(s), then you will probably benefit from putting that code in a function. ColdFusion provides many different string processing functions, but one I was surprised not to find is a ProperCase function. A ProperCase function is one that will capitalize the first letter of each word in a string, and lowercase all other letters. Often when displaying data, such as someone's name, you'll want to make sure that it is formatted properly before displaying it. That's when functions like ProperCase come in handy. I'm going to teach you how to create your own UDFs by creating a proper case function.

The ProperCase Algorithm
Before you can create a function you must first understand the block of code, or algorithm, that will be executed whenever the function is called. The requirements for the proper case function are:

  • Each letter that starts a word is turned capital.
  • A letter starts a word if the character before it is a space.
  • A letter starts a word if there is no character before it.
  • Each letter that is not the first letter of a word should be put into lowercase.
To force a character into capital or lowercase, we can use ColdFusion's built-in functions, UCase and LCase, respectively. Each one accepts a single parameter of the string to be moved upper or lower. There are many different ways to approach this coding. In our code we'll need to keep track of the current letter of the string and the previous letter of the string. We can compare the previous, or current letter, with a space or empty string to see if the letter should be put into upper or lower case. Another option might be to use an lcase on the whole string, and then loop through the string as a space delimited list. I am not using this method because ColdFusion ignores empty list elements, and our resulting string structure may not be preserved. See Listing 1 to see how we implement the code, as if it were in a normal CF page.

The code starts by setting the string we want to put in ProperCase. In normal circumstances, this string would be something we took out of a database or that was input by a user. Then we initialize variables for the current character, the previous character, and the result string. Then the code enters an index loop. The code loops from the first character in the string (character 1) to the last character of the string. The last character is determined by using the Len function on the string. Len is short for length, and it returns the number of characters in the string.

For each character in the string, we want to compare it with the previous character to decide if it goes into upper or lowercase. The first two lines in the loop set the previous value to the current value. This sounds strange, but it's what we want to do. The current variable still holds the same value as the most recent iteration of the loop, which means it is our previous value. Then the code updates the current value using the mid function. The mid function selects a number of characters out of the middle of the string. It accepts three values: the string to remove characters from, the first character we want to take, and the length of the resultant string we want. The code is pulling characters out of our str string. It starts at the current character of the string, which we can tell by using the counter variable. The length is 1 because we are comparing single characters.

The next part of the loop decides what to do with the current character. If the previous character is a space or an empty string and the current character is not a space or an empty string, then we move it to uppercase and append it to the result. This prevents us from putting empty spaces into uppercase. If the current character is not a space nor empty string, then it is put into lowercase. Otherwise we just append the character to the result string. After the loop there is additional code to output the original value and the proper case value.

The Tags Used to Create Functions
You don't want to have to write this chunk of code every time you need to put a string into proper case, do you? I didn't think so. Let's create a UDF based on this algorithm. There are two different ways to create UDFs in ColdFusion. The first is through the use of the cffunction, cfargument, and cfreturn tags. The second is to use CFScript. In ColdFusion 5, UDFs could only be created in CFScript, but ColdFusion MX introduced the tag-based syntax, which we're going to start with. It's also easier to understand for people who haven't been exposed to CFScript.

The cffunction tag is used to define the function. It accepts the following attributes:

  • Name: The name attribute specifies the name of the function. Function naming is similar to variable naming. The names of built-in CFML functions are not allowed. This is a required attribute.
  • Returntype: The returntype specifies the return type of the function. The valid values are Any, Array, Binary, Boolean, Date, guid, numeric, query, string, struct, uuid, variablename, void, or the name of a ColdFusion Component. The default is "Any", which means that anything can be returned from the function. This attribute is optional.
  • Roles: The roles attribute is used to specify the roles that are allowed to access this function. This refers to the roles that are set when a user logs in using the ColdFusion cfloginuser tag. It applies only inside a ColdFusion Component and doesn't apply to standalone functions (UDFs not inside a CFC). This attribute is optional.
  • Access: This attribute applies only to functions inside ColdFusion Components and specifies how the function exposes itself outside the CFC. The allowed values are: private, which means only code inside the component can execute this function; package, which means only code inside the component package can execute it; public, which means anyone can execute it; and remote which means it can be evoked remotely via Web services or Flash Remoting or a URL interface. This attribute is optional and defaults to "public".
  • Output: Specifies whether output will be displayed inside the component or not. If set to yes, then the body of the function will be treated as if it were inside a cfoutput. If set to no, then the body of the function will be treated as if it were inside a cfsilent. This attribute is optional and defaults to "yes".
  • Displayname: Displayname is an optional attribute used only for display in the metadata generated for a component. It has no effect on functionality.
  • Hint: The hint attribute is used to display comments or additional documentation in the component metadata. It has no effect on functionality and is optional.
The cfargument tag is used to define arguments that can be passed into the function. It must always be used inside a cffunction tag block body immediately following the opening cffunction tag. These are its arguments:
  • Name: The name attribute specifies the name of the argument and is required.
  • Type: The argument type is similar to the returntype of the cffunction tag. It specifies the type of value that is expected for this argument. The default is "any", which means that any valid value is acceptable. Other values are Array, Binary, Boolean, Date, guid, numeric, query, string, struct, uuid, variablename, void, or the name of a ColdFusion Component.
  • Required: This argument is either true or false, and it specifies whether the argument is required or not. If a required value is not passed to the function, then ColdFusion will throw an error. This is an optional argument and the default is false, or not required.
  • Default: The default attribute specifies the value that this argument will be given if it is not specified. This is mutually exclusive with the required attribute.
  • Displayname and Hint: The displayname and hint attributes are used strictly for metadata (documentation) purposes in components, just like these attributes are used with the cffunction name, and are not required.
The last tag that can be used in relation to functions is the cfreturn tag. The cfreturn tag doesn't have any attributes. It operates in a way similar to the cfif tag - you simply place an expression in the tag (there is no closing cfreturn tag). This expression is the return value.

Creating Your First Function
With an understanding of the tags that are used to create user-defined functions, you can now examine the ProperCase code turned into a function (see Listing 2).

The function starts with the cffunction tag. This is a fairly simple function declaration specifying only that there is no output inside the function, it will return a string, and the name of the function is ProperCase. Then one argument is defined, "str", which is the string that the function will put into proper case. The argument value passed is available in the arguments scope.

The next step in the function declares our local variables. Local variables in functions are private to the function - this means that they are protected from variables with the same name in other pages and functions and that they don't expose themselves outside of the function. Private variables are put in an unnamed scope, so you only access it by the variable name with no scope specified. Local variables must be declared at the beginning of the function immediately following any arguments. They are done using the cfset tag with the var keyword. As a best practice, be sure to var all variables used in the function that you do not want to exist outside of the function. This includes the counter variable, which we use in the loop. The current character, previous character, and result string values are all initialized.

The meat of the code remains almost identical to our initial code. In fact I copied and pasted it from the CF page inside the function page. I made one slight change, to specify the argument scope whenever the str variable is referenced. The last line of the function uses the cfreturn tag to return the result string. If you test the code you'll find it runs no differently than the brute force code approach, but is now easily executed from any part of my files - reusability achieved!

Conclusion
The most common way to call a user-defined function is to do so the same way as a built-in function. You can call it within any ColdFusion expression. There is an alternate way, including using the cfinvoke tag, if the function is part of a ColdFusion Component. Additionally, there is a CFScript syntax for writing your own functions. You can read more about that at http://livedocs.macromedia.com/coldfusion/6.1/htmldocs/udfs5.htm. Before you go about writing your own function, you may want to check to see if it exists at the common function library project, found at www.cflib.org. cflib is a great learning and development resource and you'll find many functions to do many different things. Next month I'm going to take a look at ColdFusion Components. While functions are great for modularizing functionality, components allow you to modularize both data and functionality.

More Stories By Jeffry Houser

Jeffry is a technical entrepreneur with over 10 years of making the web work for you. Lately Jeffry has been cooped up in his cave building the first in a line of easy to use interface components for Flex Developers at www.flextras.com . He has a Computer Science degree from the days before business met the Internet and owns DotComIt, an Adobe Solutions Partner specializing in Rich Internet Applications. Jeffry is an Adobe Community Expert and produces The Flex Show, a podcast that includes expert interviews and screencast tutorials. Jeffry is also co-manager of the Hartford CT Adobe User Group, author of three ColdFusion books and over 30 articles, and has spoken at various events all over the US. In his spare time he is a musician, old school adventure game aficionado, and recording engineer. He also owns a Wii. You can read his blog at www.jeffryhouser.com, check out his podcast at www.theflexshow.com or check out his company at www.dot-com-it.com.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


IoT & Smart Cities Stories
Moroccanoil®, the global leader in oil-infused beauty, is thrilled to announce the NEW Moroccanoil Color Depositing Masks, a collection of dual-benefit hair masks that deposit pure pigments while providing the treatment benefits of a deep conditioning mask. The collection consists of seven curated shades for commitment-free, beautifully-colored hair that looks and feels healthy.
The textured-hair category is inarguably the hottest in the haircare space today. This has been driven by the proliferation of founder brands started by curly and coily consumers and savvy consumers who increasingly want products specifically for their texture type. This trend is underscored by the latest insights from NaturallyCurly's 2018 TextureTrends report, released today. According to the 2018 TextureTrends Report, more than 80 percent of women with curly and coily hair say they purcha...
The textured-hair category is inarguably the hottest in the haircare space today. This has been driven by the proliferation of founder brands started by curly and coily consumers and savvy consumers who increasingly want products specifically for their texture type. This trend is underscored by the latest insights from NaturallyCurly's 2018 TextureTrends report, released today. According to the 2018 TextureTrends Report, more than 80 percent of women with curly and coily hair say they purcha...
We all love the many benefits of natural plant oils, used as a deap treatment before shampooing, at home or at the beach, but is there an all-in-one solution for everyday intensive nutrition and modern styling?I am passionate about the benefits of natural extracts with tried-and-tested results, which I have used to develop my own brand (lemon for its acid ph, wheat germ for its fortifying action…). I wanted a product which combined caring and styling effects, and which could be used after shampo...
The platform combines the strengths of Singtel's extensive, intelligent network capabilities with Microsoft's cloud expertise to create a unique solution that sets new standards for IoT applications," said Mr Diomedes Kastanis, Head of IoT at Singtel. "Our solution provides speed, transparency and flexibility, paving the way for a more pervasive use of IoT to accelerate enterprises' digitalisation efforts. AI-powered intelligent connectivity over Microsoft Azure will be the fastest connected pat...
There are many examples of disruption in consumer space – Uber disrupting the cab industry, Airbnb disrupting the hospitality industry and so on; but have you wondered who is disrupting support and operations? AISERA helps make businesses and customers successful by offering consumer-like user experience for support and operations. We have built the world’s first AI-driven IT / HR / Cloud / Customer Support and Operations solution.
Codete accelerates their clients growth through technological expertise and experience. Codite team works with organizations to meet the challenges that digitalization presents. Their clients include digital start-ups as well as established enterprises in the IT industry. To stay competitive in a highly innovative IT industry, strong R&D departments and bold spin-off initiatives is a must. Codete Data Science and Software Architects teams help corporate clients to stay up to date with the mod...
At CloudEXPO Silicon Valley, June 24-26, 2019, Digital Transformation (DX) is a major focus with expanded DevOpsSUMMIT and FinTechEXPO programs within the DXWorldEXPO agenda. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive over the long term. A total of 88% of Fortune 500 companies from a generation ago are now out of business. Only 12% still survive. Similar percentages are found throug...
Druva is the global leader in Cloud Data Protection and Management, delivering the industry's first data management-as-a-service solution that aggregates data from endpoints, servers and cloud applications and leverages the public cloud to offer a single pane of glass to enable data protection, governance and intelligence-dramatically increasing the availability and visibility of business critical information, while reducing the risk, cost and complexity of managing and protecting it. Druva's...
BMC has unmatched experience in IT management, supporting 92 of the Forbes Global 100, and earning recognition as an ITSM Gartner Magic Quadrant Leader for five years running. Our solutions offer speed, agility, and efficiency to tackle business challenges in the areas of service management, automation, operations, and the mainframe.