Defining components and functions in CFScript

ColdFusion supports the syntax for defining CFCs, including interfaces, functions, properties, and parameters entirely in CFScript. Currently, however, only certain ColdFusion tags are supported as CFScript functions. This section describes the component definition syntax.

For information on tags as functions see Tag equivalents in CFScript.

Basic Syntax

Syntax for defining a component is as follows:

/** 
* ColdFusion treats plain comment text as a hint. 
* You can also use the @hint metadata name for hints. 
* Set metadata, including, optionally, attributes, (including custom 
* attributes) in the last entries in the comment block, as follows: 
*@metadataName metadataValue 
... 
*/ 
component attributeName="attributeValue" ... { 
body contents 
}

The following example shows a simple component definition

/** 
* Simple Component. 
*/ 
component { 
/** 
* Simple function. 
*/ 
public void function foo() { 
WriteOutput("Method foo() called<br>"); 
} 
}

When you define a component entirely in CFScript, you do not have to use a cfscript tag on the page. In this case, the component keyword can be preceded only by comments (including metadata assignments) and import operators. Adobe recommends this format as a best practice. You specify component properties as follows:

/** 
/*@default defaultValue 
* @attrib1Name attrib1Value 
* ... 
*/ 
property [type]propName;

If the type precedes the property name, you do not need to use the "type" keyword, only the name of the specific type. In either format, you must set the name attribute value. All other property attributes, such as type, are optional. As with cfproperty tags, place the property operators at the top of the component definition, immediately following the opening brace.

The syntax to define a function is similar to the component definition:

/** 
*Comment text, treated as a hint. 
*Set metadata, including, optionally, attributes, in the last entries 
*in the comment block, as follows: 
*@metadataName metadataValue 
... 
*/ 
access returnType function functionName(arg1Type arg1Name="defaultValue1" 
arg1Attribute="attributeValue...,arg2Type 
arg2Name="defaultValue2" arg2Attribute="attributeValue...,...) 
functionAttributeName="attributeValue" ... { 
body contents 
}

You specify all function arguments, including the argument type, default value, and attributes in the function definition.

The following example shows a function definition:

/** 
* @hint "This function displays its name and parameter." 
*/ 
public void function foo(String n1=10) 
description="does nothing" hint="overrides hint" ( 
WriteOutput("Method foo() called<br> Parameter value is " & n1); 
}

Specifying the required keyword makes the argument mandatory. If the required keyword is not present then the argument becomes optional.

For example:

public function funcname(required string argument1)

Interface definitions follow the same pattern as components, with the same general rules and limitations that apply to the interfaces you define using cfinterface tags. The following simple code defines an interface with a single function that takes one string argument, with a default argument value of "Hello World!":

interface { 
function method1(string arg1="Hello World!"); 
function method2 (string arg1="Goodbye World!"); 
... 
}

The following example shows the definition of a simple component with a single function:

/** 
* Component defined in CFScript 
* @output true 
*/ 
component extends="component_01" { 
/** 
* Function that displays its arguments and returns a string. 
* @returnType string 
*/ 
public function method_03(argOne,argTwo) { 
WriteOutput("#arguments.argOne# "); 
WriteOutput("#arguments.argTwo# "); 
return("Arguments written."); 
} 
}

Setting attributes

The definition syntax provides two ways to set attributes:

  • At the end of a comment that immediately precedes the element, in the following format

    /** 
    *Comment 
    *@attributeName1 attributeValue 
    *@attributeName2 attributeValue 
    *... 
    */
  • In the element declaration using standard attribute-value assignment notation, as in the following line:

    component extends="component_01"

Attribute values set in the element declaration take precedence over the values set in the comment section. Therefore, if you set an attribute, such as a hint in both locations, ColdFusion ignores the value in the comment section and uses only the one in the element declaration.

Specifying page encoding

You can specify the character encoding of a component by specifying a pageencoding processing directive at the top of the component body. You can specify the pageencoding directive only for components. The following code snippet shows how to use the directive:

// this is a component 
/** 
*@hint "this is a hint for component" 
*/ 
component displayname="My Component" { 
pageencoding "Cp1252" ; 
// 
// The rest of the component definition goes here. 
// 
}
Note: Currently, you cannot use CFScript to specify the suppresswhitespace processing directive.

Accessing component metadata

To access metadata of a component, function, parameter, or property, use the GetMetadata function. Component metadata includes the metadata of its properties and functions, including attributes and function parameters.

For detailed information about the structure and contents of the metadata, see GetMetaData in the CFML Reference.

The following trivial code shows the use of component metadata:

//Create an instance of a component. 
theComponent=createObject("Component" "myComponent"); 
// Get the component metadata. 
theMetadata = getMetadata(theComponent); 
// The component properties are in an array. Display the name 
// of the first property in the array. 
writeoutput("Property name: " & theMetadata.properties[1].name);

Support for creating custom metadata

Note: To use this feature, you must install ColdFusion 9 Update 1.

You can specify custom metadata for function arguments in script syntax in either of the following ways:

  • With arguments, as space-separated list of key-value pairs.

  • In annotations, using @arg1.custommetadata "custom value".

Example

custom.cfm

cfscript> 
                writeoutput(new custom().foo(10)); 
</cfscript>

custom.cfc

/** 
 * custom metadata for a cfc defined using annotation as well as key-value pairs 
 * @cfcMetadata1 "cfc metadata1" 
 */ 
component cfcMetadata2 = "cfc metadata2" 
{ 
                /** 
                 * custom metadata for a property defined using annotation as well as key-value pairs 
                 * @propMetadata1 "property metadata1" 
                 */ 
                property type="numeric" name="age" default="10" propMetadata2="property metadata2"; 
                
                /** 
                 * custom metadata for a function/argument using both annotation and key-value pairs 
                 * @arg1.argmdata1 "arg metadata1" 
                 * output true 
                 * @fnMetadata1 "function metadata1" 
                 */ 
                public string function foo(required numeric arg1=20 argmdata2="arg metadata2") fnMetadata2="function metadata2" 
                { 
                                writedump(getmetadata(this)); 
                                return arg1; 
                } 
}

Explicit function-local scope

ColdFusion has an explicit function-local scope. Variables in this scope exist only during the execution of the function and are available only to the function. To declare a function-local scope variable either specify the Local scope name when assigning the variable, or use the var keyword. Also, you can now use the var keyword anywhere in a function definition, not just at the top.

Note: Because it is now a scope name, do not use local as a variable or argument name. If you do so, ColdFusion ignores the variable or argument.

The following code shows the use of the function local scope:

<cffunction name="foo" output="true"> 
<cfset var x = 5> 
<cfset local.y=local.x*4> 
<cfset var z=[local.x,local.y]> 
<cfset local.u.v={z="2"}> 
<cfset zz="in Variables Scope"> 
<cfdump var="#local#"> 
</cffunction>;

For more information about function local scope see Using ColdFusion Variables.

Using system level functions

In the <cfscript> mode, you can now use the following basic language constructs:

  • throw

  • writedump

  • writelog

  • location

  • trace

You can call these functions by passing the argument as name=”value” pairs or positional notations. For positional notations, the sequence of arguments must be followed. The sequence of arguments for each construct is mentioned in the CFML Reference Guide.

Example of passing arguments as name=value pair:

<cfscript> 
    writedump(var=myquery, label="query", show="name", format = "text"); 
</cfscript>

Example of passing arguments as Positional arguments:

<cfscript> 
    writedump(myquery, false, html, name); 
</cfscript>

You do not need to specify all the parameters while using positional arguments. For instance, if you want to specify the first and third argument, you can add an empty value for the second argument. The exception to this usage is when there is a boolean type for the second argument where you have to specify true or false.

Note: You cannot mix positional and named arguments while calling a function. For example, if you need to use only the var and output attributes with the writedump construct, you can use writedump(myquery,html).