Functions
Functions are the way to interact with objects, with no functions we have no object-oriented behaviors, no abstractions and no encapsulation. Functions have an automatic return type of any
which means it can return any type of variable back to a user and an automatic visibility scope of public
. They also can take in ANY amount of arguments, which don't even have to be defined in the function signature. WOWZA!
Functions in CFML are also first-class object citizens. Meaning that each function can be addressed like an object. They can be even deleted, renamed or even injected at runtime. This is one of the most powerful qualities of the CFML dynamic language. You can at runtime manipulate objects and their functions.
You can find all the different features of functions in the docs: https://cfdocs.org/cffunction
Declaration
Examples
Please note that you can use valid JavaDoc syntax and DocBox will document your functions and arguments as well.
Function Access Types and Scopes
Functions can have different visibility contexts:
public
- Available to the component and externallyprivate
- Available only to the component that declares themethod and any components that extend the component in
which it is defined
package
- Available only to the component that declares themethod, components that extend the component, or any
other components in the package
remote
- Available to a locally or remotely executing pageor component method, or a remote client through a URL,
Flash, or a web service. To publish the function as a
web service, this option is required.
Another interesting tidbit in CFML is that the visibility determines where the function will exist within the scope of the CFC. Remember that functions in CFML are objects themselves. They can be added, removed, renamed even at runtime thanks to CFML being a dynamic language.
public,remote
- The function reference is placed in both thethis
andvariables
scopeprivate,package
- The function reference is placed in thevariables
scope
Does this mean, that I can programmatically change an object at runtime by injecting (mixing) in new methods, or removing methods, or even renaming them? HECK YES SIREE BOB! This is the beauty of the dynamic language, you can manipulate object instances at runtime.
Function Modifiers
Function modifiers allows you to declare special behaviors to functions, from static
availability to final
and abstract
declarations. The supported modifiers for CFML functions by CFML engine are the following:
We have created a section for each of these types, so you can read more about the modifiers:
Function Attributes & Metadata
The function
construct can also have many attributes or name-value pairs that will give it some extra functionality according to CFML engine (metadata). You can find all of them here: https://cfdocs.org/cffunction. Below are the most common ones:
output
- Will this function send content to the output stream. Try avoiding this totrue
unless you are building libraries of some type, else you are breaking encapsulationdescription
- A short text description of the function a part from the hintreturnFormat
- Format to return for remote callers
Please note that in CFML you can also declare these attributes via annotations in the comments section:
Apart from the name-value pairs of attributes the CFML language gives you, you can also add your own. These are called function annotations or custom function metadata. They can be anything you like and they don't even have to have a value. The CFML engines then gives you the ability to read the metadata out of the functions via the getMetadata()
or getComponentMetadata()
functions.
Function Arguments
Arguments tell the function how to do their operation. A function can receive zero or more arguments separated by commas in its declaration.
declaration
All CFML functions are dynamic, meaning it can take any number of arguments without you even adding the signatures. You can call functions by passing arguments by position or via name-value pairs or even with a structure/array of values, which will be called an argumentCollection
.
example
Tip: Please also note that you can add a-la-carte metadata or name-value pairs to each argument inline or via annotations like we have seen above.
example with annotations
Function Returns
CFML functions will use the return
keyword to return a value from the function. A function can be marked void
in its return type to denote that it does not return any value. However, if a function has no return type or any
and you do not return explicitly a value, then the function will automatically return null
.
Function Scopes
You must be getting into the habit of scopes by now. Functions also has access to all Component scopes plus a few more that are only available to the function itself.
arguments
- Collects all the incoming arguments. If the function is called via positional, then this will be a struct with numbers as keys. If the function is called via name-value pairs, then the struct will contain the same name-value pairs.local
- A struct that contains all the variables that are ONLY defined in the functions via thevar
keyword.
Function Var Scope or Local Scope
Each function has a local
scope that is ONLY available for the life-time of the execution of the function. This is where you will be defining localized variables since your object can be multi-threaded. Always Always Always plan for multi-threaded applications and make sure you var scope your variables. Why? Well, if you do not var scope a variable then your variable will end up in the implicit scope which is variables
.
CFML also has a weird cascading lookup for variables, so if you do not explicitly specify the scope it is in, CFML will look for it for you. If you use a variable name without a scope prefix, CFML checks the scopes in the following order to find the variable:
Local (function-local, UDFs and CFCs only)
Arguments
Thread local (inside threads only)
Query (not a true scope; variables in query loops)
Thread
Variables
CGI
Cffile
URL
Form
Cookie
Client
Because CFML must search for variables when you do not specify the scope, you can improve performance by specifying the scope for all variables.
Executing Functions
You can execute functions once you have an instance or reference of a component. If the function has arguments, you can pass them in three ways: positional, name-value pairs, or using a collection (array,struct) via the argumentCollection
attribute.
Last updated