580 likes | 706 Views
Building User Defined Functions (UDF). Speaker: Jo Belyea-Doerrman jobdoer@teratech.com TeraTech Consultant. Speaker Information. Who am I? ColdFusion Developer ColdFusion Developer since 1997 Teach one-on-one and custom classes for TeraTech. This Session. This session I will:
E N D
Building User Defined Functions (UDF) Speaker: Jo Belyea-Doerrman jobdoer@teratech.com TeraTech Consultant
Speaker Information Who am I? • ColdFusion Developer • ColdFusion Developer since 1997 • Teach one-on-one and custom classes for TeraTech
This Session This session I will: • introduce you to the brave new world of user-defined functions (UDFs); • demonstrate two ways to create your own functions; • show you where to get UDFs others have written.
Extend CFML • One of the advantages of CF is that it is extensible. • CFML can be easily extended beyond the tags and functions that are built-in.
4 ways to extend Cold Fusion • User-Defined Functions • Custom Tags • ColdFusion Components (CFCs) • CFX Tags This session focuses on UDFs.
What are UDFs? Simply put, UDFs are functions that you create and/or share. If you feel that some function is missing from CF – make it yourself!
CFUN04 cfun04 User-Defined Functions (UDFs) • Think of them as little engines on an assembly line • Accepts input – runs it through the function and creates some kind of corresponding output • Now can be built with CFFUNCTION, CFARGUMENT CFRETURN tags. Ucase()function
Why use UDFs instead of Custom Tags? • Only UDFs provide the convenience of return values. • Custom tags can create values (as Caller.VariableName) that are accessible to the calling template after their execution, but with UDFs the return value is the primary goal of the function.
Why use UDFs? Cont. • Performance may be worth some consideration when deciding to use UDFs or custom tags. • If a function is to be performed multiple times within one template, a UDF would most likely out-perform the custom tag. This is due to the fact that processing does not have to leave the template every time a UDF is executed. With the custom tag, it goes out to the tag itself each time processing of the task is required.
What’s new? • Completely overhauled in CFMX. • Can be written with Cold Fusion tags or using CFSCRIPT • No longer have to write UDFs with CFSCRIPT – strongly recommend using <CFFUNCTION> rather than this method • Note: If you are writing UDFs in CF5 you must still write them in CFSCRIPT
Basic steps to a UDF with tags To create a user-defined function you will need to four basic steps that use the following tags: • CFFUNCTION • CFARGUMENT • CFRETURN
Step 1 • Start with a pair of <CFFUNCTION> tags. All the code you need to make the function do its work goes in between these tags.
Step 2 • <CFARGUMENT> Add each argument your function will be using for input. Can make required or optional.
Step 3 • Add any CFML code that is needed to make your function work. Can use whatever tags and functions you want.
Step 4 • The last step uses the <CFRETURN> tag. It specifies what your functions output should be.
Building Your First UDF You may find yourself wanting a function that pulls an employees e-mail address from the db. You could use this: <CFOUTPUT>#getEmployeeEmail(8)# </CFOUTPUT> You could create it using the old <CFQUERY> tag…however, you can also turn this into a function very easily!
Let’s look at some code! • We’ll call the UDF GetEmployeeEmail()
GetEmployeeEmail() <CFFUNCTION name=“GetEmployeeEmail”> <CFARGUMENT NAME=“EmployeeID” TYPE=“Numeric” REQUIRED=“Yes”> <!---Get the Employee’s email---> <CFQUERY Name=“getEmployee” DATASOURCE=“#datasource# CACHEDWITHIN=“#CreateTimespan(0,1,0,0)#”> SELECT EmployeeEmail FROM Employees WHERE #ARGUMENTS.EmployeeID# </CFQUERY> <!--- Return the employee’s email ---> <CFRETURN getEmployee.EmployeeEmail> </CFFUNCTION>
Using the Function Once written, this can be used like any other function. When CF sees the function -- It runs the code between the corresponding <CFFUNCTION> tags. Arguments can be: • Static <CFOUTPUT>#GetEmployeeEmail(8)#</CFOUTPUT> • Dynamic <CFOUTPUT>#GetEmployeeEmail(FORM.ShowEmployeeID) </CFOUTPUT> • Used within <CFSET> <CFSET myEmployeeLowerCase = Lcase(GetEmployeeEmail(FORM.ShowEmployeeID))>
<CFFUNCTION> • NAME – You will call the function using the name provided here. Must be a valid CFML identifier. • RETURNTYPE – Optional. Type of info the function will return. String, numeric, date and so on. Use to make functions more self-documenting.
<CFARGUMENT> • NAME – The name of the argument. • TYPE – Optional. The data type that should be supplied to the argument. If you supply a TYPE, CF will display an error if someone tries to use the function with the wrong kind of input. • REQUIRED – Optional. Default is “No”. • DEFAULT – Optional. For optional arguments (REQUIRED = “No”), the value of the argument when the value is not passed in.
Required Arguments • <CFARGUMENT … REQUIRED = “Yes”> Argument must be provided the function is actually used. If the argument is not provided at runtime, CF will display an error message.
Optional Arguments • If REQUIRED=“no” and a default has been specified then the function can be called either with or without the argument at runtime. • If the value IS provided, the value will be what is presented in the ARGUMENTS scope. • If not, the DEFAULT value will be used • If REQUIRED=“no” and a default has NOT been specified then the function still optional. You can use the IsDefined() function to determine whether the argument is provided at runtime.
<CFRETURN> • Return value can be any expression • Has no attributes per se. Instead, you determine whatever string, number, date, variable or expression you want directly returned within the <CFRETURN > tag. • Examples: <CFRETURN “a”> <CFRETURN TimeFormat(Now())> <CFRETURN “The current time is: “& TimeFormat(Now())>
Don’t show variables • Most times you don’t want variables to be visible to pages that use the function • You need to tell CF that a particular variable should only be visible within the context of the <CFFUNCTION> block. • Don’t want function to have “side effects”. • Should not have to worry about its overwriting any variables already defined Called a Local Variable
Using Local Variables <CFSET var myLocalVariable = “Hello”> The var keyword tells CF that the variable should cease to exist when <CFFUNCTION> block ends.
Local Variable Rules • Can declare as many as you want. Use separate <CFSET> for each, using the var keyword each time. • <CFSET> must be at the very top of <CFFUNCTION> block right after the <CFARGUMENT> tags.
Local Variable Rules cont. • Can not declare without a value. There must be an = sign with an initial value. Can change later in the functions code.
Where to Save Your UDFs • You can Create and Use UDF in the same file or • Save UDFs in Separate Files for easy reuse • Reusing code saves time and effort • <CFINCLUDE> function code • If you want function available at the application level, <CFINCLUDE> function code in Application.cfm
Creating Libraries of Related UDFs • No specific rules what kinds of UDFs can be collected into a library. • Makes sense to group your UDFs into different files according to some kind of common concept • UDFs can call other UDFs in the same file. • They can even call functions in other files as long as the <CFINCLUDE> tag has been used to include the other files
Uses for UDFs • Adding “Tags” to CFSCRIPT
Adding “Tags” to CFSCRIPT • Another good use is when wanting to do something only supported by tags within a CFSCRIPT block • For instance, may want to do a CFDUMP in a script • Can’t use that tag in CFSCRIPT • But can create UDF to do it and call that from script
CFFUNCTION_dumpudf code <!--- cffunction_dumpudf.cfm ---> <cffunction name="dump"> <cfargument name="var"> <cfargument name="label" required="no" default=""> <cfoutput>#arguments.label#</cfoutput> <cfdump var="#arguments.var#"> <br></cffunction>
Adding “Tags” to CFSCRIPT • You can now call it just like any other UDF • In this example, calling inside CFSCRIPT • Not a requirement. Can call outside CFSCRIPT too
Calling <!--- other\call_dumpudf.cfm ---> <cfinclude template="cffunction_dumpudf.cfm"> <cfscript> // while creating code in CFSCRIPT you often want to dump something // server scope is something we can now dump in CFMX dump(var="#server#"); // or simply dump(server); </cfscript>
Benefits Over CFSCRIPT UDFs • Besides ability to use tags within UDF • More important point may be ability to use CFARGUMENT, and ReturnType on CFFUNCTION • These give greater control over data types over data coming into and going out of UDF • and required/optional support for arguments coming in
Benefits Over CFSCRIPT UDFs • Also, can use the ROLES attribute on CFFUNCTION to limit use by authorized users (see CFLOGINUSER) • Also, in script, there is no equivalent to CFTHROW • Still, the choice will more often be one of programming style • Each approach has its place
UDF written with CFSCRIPT function TempConvert(ATemp, ItsScale) { if (not IsNumeric(ATemp)) return "NAN"; if (UCase(ItsScale) eq "F") // temp given in Fahrenheit. Convert to Celsius degs = (ATemp - 32.0) * ( /9.0); else if (UCase(ItsScale) eq "C") // temp given in Celsius. Convert to Fahrenheit degs = (ATemp * 9.0/5.0) + 32; else degs = "Not a valid scale"; ; return degs; } 50 degrees Fahrenheit is #TempConvert("50","F")# degrees Celsius.
Calling the UDF • Call the UDF by using the following: 50 degrees Fahrenheit is #TempConvert("50","F")# degrees Celsius.
What does it do? • Prints "50 degrees Fahrenheit is 10 degrees Celsius."
How does it work? Two arguments are passed to the function: a temperature and the scale that it is in. The temperature is checked to make sure it's a number (the value "NAN" is returned and processing ends if it is not). Then the calculation is processed based on the scale being "F" or "C." If the scale given is neither "F" nor "C," the message "Not a valid scale" is returned.
Rules for function definitions The following rules apply to functions that you define using CFScript or the CFFunction tag: • The function name must be unique. It must be different from any existing variable, UDF, or built-in function name. • The function name must not start with the letters cf in any form. (For example, CF_MyFunction cfmyFunction, and cfxMyFunction are not valid UDF names.)
Rules cont. • You cannot redefine or overload a function. If a function definition is active, ColdFusion generates an error if you define a second function with the same name. • You cannot nest function definitions; that is, you cannot define one function inside another function definition.
Rules cont. • The function can be recursive, that is, the function definition body can call the function. • The function does not have to return a value
Define a function in the following places: • On the page where it is called. You can even define it below the place on the page where it is called, but this poor coding practice can result in confusing code.
Define a function in the following places: • On any page that puts the function name in a scope common with the page on which you call the function.
Define a function in the following places: • On a page that you include using a cfinclude tag. The cfinclude tag must be executed before the function gets called. For example, you can define all your application's functions on a single page and place a cfinclude tag at the top of pages that use the functions.
Define a function in the following places: • Application.cfm page. Consider the following techniques for making your functions available to your ColdFusion pages on the following pages.
Using Application.cfm and function include files • If you consistently call a small number of UDFs, consider putting their definitions on the Application.cfm page.