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
- Declaring Functions
- Conditional Logic - if / elseif / else
- Conditional Logic - switch
- Loops: for
- Loops: while
- Loops: do / while
- Exception Handling: try / catch / finally
- abort / exit
- Object creation: import / new
- Parameter Initialization
- Locking blocks
- Thread Creation
- Transaction
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 functionThe 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>