Using <CFSCRIPT>

CFSCRIPT brings the power of a fully blown language deep inside your CFML applications. Not dissimilar to Javascript, you can easily and quickly build complete blocks of code, including functions, to easily build out logic. All of the standard CFML functions are available including any User Defined Functions (UDF).

Statements are written usually one per line, but the delimiter is the semi-colon (;). Be careful with {} brackets, for everyone you open, you have to close.

Simple Constructs

Writing cfscript code is quick - declare the CFSCRIPT tag and place your script code inside the tags.

<cfscript>

// This is a comment
// Declaring a variable
x = 0;

/*
 * You can also put comments in blocks like this
 */
WriteOutput( "Outputs content" );

</cfscript>

Declaring Functions

Any function declared inside a CFSCRIPT block is available as a UDF. You declare functions inside in CFC's using this technique instead of CFFUNCTION.

<cfscript>

function myFunction( param1, param2 ){
  var x = arguments.param1;
  var y = arguments.param2;
  return x+y;
}

</cfscript>

Functions have in themselves plenty of parameters you can use.

Defining Attributes of the function

The attributes of the function can be declared between the last ")" and the "{" as a key=value pair. All the attributes available to CFFUNCTION can be expressed here.

[public|private|remote|package] [returntype] function myFunction( param1, param2 )
  [output=true foo="bar" description="my description" roles="my roles" hint="my hint" displayname="my displayname"]
{
}

An example of this in use.

<cfscript>

// Marks this function as private
private numeric function myFunction( param1, param2 )
  hint="this is a private function"
{
  var x = arguments.param1;
  var y = arguments.param2;
  return x+y;
}

</cfscript>
Defining Attributes of the arguments

Attributes for a function are usually expressed in CFARGUMENT tag. You can pass in the same attributes but more the style of traditional langauges.

function myFunction( [required] [type] param1[="default value"] )

An example of this in use.

<cfscript>

// Marks this function as private
private function myFunction( required numeric param1, Array param2="#[1,2,3]#" )
  hint="this is a private function"
{
  var x = arguments.param1;
  var y = arguments.param2[1];
  return x+y;
}

</cfscript>

Conditional Logic - if / elseif / else

You can easily utilise conditional logic inside your script, utilising all the usual operators associated with Javascript/Java.

<cfscript>

if ( isDefined("form.name") ){
  // do something
} else if ( isDefined("form.age") && form.age > 19 ) {
  // do something
} else {
  // do something
}

</cfscript>

Conditional Logic - switch

The switch statement is a good alternative to multiple if statements

<cfscript>

switch (form.name){
  case "alan":
    WriteOutput( "Welcome Alan" );
    break;

  case "andy":
    WriteOutput( "Welcome Andy" );
    break;

  case 321:
    WriteOutput( "321" );
    break;

  default:
    WriteOutput( "Welcome" );
}

</cfscript>

Looping: for

You can loop over data in a variety of ways using CFSCRIPT.

<cfscript>

// Looping Simple
for ( x=1; x <= 5; x++ ){
  WriteOutput( x );
}


// Looping over an array
myArray = ["openbd","openbluedragon"];
for ( x=1; x <= ArrayLen(myArray); x=x+1 ){
  WriteOutput( myArray[x] );
}


// Looping over a collection/struct
myStruct = {
  name : "alan",
  location : "scotland"
};
for ( key in myStruct ){
  WriteOutput( myStruct[key] );
}


// Looping over an array
myArray = ["alan","andy","ceri"];
for ( arrElement in myArray ){
  WriteOutput( arrElement );
}


// Looping over query
qry = QueryNew( 'name' );
QueryAddrow( qry, 1 );
QuerySetCell( qry, 'name', 'Andy' );
QueryAddRow( qry, 1 );
QuerySetCell( qry, 'name', 'Alan' );

for ( x=1; x <= qry.recordcount; x++ ){
  writeoutput( qry.name[x] );
}

</cfscript>

You can easily break out of a loop or skip to the next iteration using the keywords: continue and break.

In addition, if you are inside a function you can declare the variable there and then inside the for() block:

<cfscript>

function xyx(){

  // Looping Simple
  for ( var x=1; x <= 5; x++ ){
    WriteOutput( x );
  }

}
</cfscript>

Looping: while

<cfscript>

// Looping Simple
x = 0;
while ( x < 10 ) {
  WriteOutput( x );
  x++;
}

</cfscript>

Looping: do

An alternative is to use do/while construct. Particularly handy if you know you want to execute the body of the loop at least once.

<cfscript>

// Looping Simple
x = 0;
do{
  WriteOutput( x );
  x++;
} while ( x < 10 );


// Looping over query
qry = QueryNew( 'name' );
QueryAddrow( qry, 1 );
QuerySetCell( qry, 'name', 'Andy' );
QueryAddRow( qry, 1 );
QuerySetCell( qry, 'name', 'Alan' );

qry.reset();
while ( qry.nextRow() ) {
  writeoutput( qry.name );
}

</cfscript>

Exception Handling: try / catch / finally

You can easily trap for exceptions using the standard try/catch mechanism, with the optional finally block. The finally block will always execute, even if an exception is thrown. This is very useful when you want to clean up resources (delete a temp file) irrespective of whether or not an exception is thrown.

<cfscript>
try{

} catch( Any e ){

} finally {

}
</cfscript>

Alternatively, you can throw exceptions to indicate something has gone wrong. You can also use the throw() function that lets you control all aspects of the throw exception. If you are already inside a catch block you can rethrow the exception to the next level.

<cfscript>
// Throw an exception
throw;

// Throw with an error
throw "Stopping Now";

// Using the function alternative
throw("Application","Message","Extra Detail","errorcode","extendinfo");

// Rethrow
try{

}catch(Any e){
  rethrow;
}
</cfscript>

abort / exit

You can stop the processing of the current request immediately using the abort keyword, or using the exit you can exit the current loop, tag, or file.

<cfscript>
// Stop now
abort;

// Stop now, with an optional message
abort "Stopping Now";

// Exits
exit;

// Exit the tag
exit "exittag";

// Exit the loop
exit "loop";
</cfscript>

Object creation: import / new

There is a more Java like way of creating your objects. Instead of using CreateObject(), you can now use the new Object() syntax, in much the same way you would declare objects in Java.

In addition to this, the unofficial/official constructor for CFC's, the init() function, is also called at object creation time, if found. Which incidentally means, that the init() function no longer needs to return back "this" which is the standard pattern in CFC creation at the moment. Naturally, you can still do that with no side effects.

The import statement defines the packages/paths that will be searched for the CFC when you are using the "new" operator.

<cfscript>
import "org.openbluedragon.importexample";
import org.openbluedragon.importexample;

obj = new Test();
obj = new Test( arg1, arg2 );
obj = new org.openbluedragon.importexample.Test();
</cfscript>

Parameter Initialization

Instead of using CFPARAM tag outside of the CFSCRIPT block, you can utilise this powerful directive to initalize your variables in a single statement instead of complicated if blocks.

<cfscript>
// check "foo" exists
param name="foo";

// check 'bar' is of string type and default 'bar' to "foo" if it doesn't already exist
param name="bar" type="string" default="foo";

// check retest is defined and contains alpha chars only
param name="retest" type="regex" pattern="[a-zA-Z]+";
</cfscript>

Locking blocks

Instead of using CFLOCK tag to lock blocks of CFML code from concurrent execution, you can use the lock directive.

<cfscript>
lock name="testlock" timeout="5" type="exclusive" {
  // lock body

}
</cfscript>

Thread Creation

Instead of using CFTHREAD tag to create blocks of concurrent execution, you can simply declare them using the thread directive.

<cfscript>
thread name="thread1" {
  // thread body
}

thread name="thread2" foo="bar" {
  // thread body
}
</cfscript>

Once created, you have control over how you interact with the threads.

<cfscript>
// sleep for 50ms
thread action="sleep" duration="50";

// terminate thread1
thread action="terminate" name="thread1";

// join on thread1 and thread2
thread action="join" name="thread1,thread2";
</cfscript>

Transaction

Instead of using CFTRANSACTION tag to create blocks of transaction SQL execution, you can simply declare them using the transaction directive.

<cfscript>
transaction action="begin" {

  ...

  if ( someConditional ){
    transaction action="rollback";
  }else{
    transaction action="commit";
  }

  ...
}
</cfscript>