Coldfusion - Developing ColdFusion Applications
Coldfusion - Developing ColdFusion Applications
MacroMedia ColdFusion 5
Macromedia Incorporated
Copyright Notice
19992001 Macromedia Incorporated. All rights reserved. This book, as well as the software described in it, is furnished under license and may be used or copied only in accordance with the terms of such license. The content of this manual is furnished for informational use only, is subject to change without notice, and should not be construed as a commitment by Macromedia, Incorporated. Macromedia, Incorporated assumes no responsibility or liability for any errors or inaccuracies that may appear in this book. Except as permitted by such license, no part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, electronic, mechanical, recording, or otherwise, without the prior written permission of Macromedia, Incorporated. ColdFusion, HomeSite, and Macromedia are registered trademarks of Macromedia Incorporation in the United States and internationally. Allaire Spectra, the Allaire Spectra logo, Generator, Macromedia Generation, and JRun are trademarks of Macromedia, Incorporated. Java is a trademark of Sun Microsystems, Inc. Microsoft, Windows, Windows NT, Windows 95, Microsoft Access, and FoxPro are registered trademarks of Microsoft Corporation. PostScript is a trademark of Adobe Systems Inc. Solaris is a trademark of Sun Microsystems Inc. UNIX is a trademark of The Open Group. All other company names, brand names, and product names are trademarks of their respective holder(s).
Contents
...............................
xv
Intended Audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi New Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi Developer Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii About ColdFusion Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xviii Printed and online documentation set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix Viewing online documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix Printing ColdFusion documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix Getting Answers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx Contacting Macromedia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx
..............
1
3 3 3 3
A Quick Web Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Before You Begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Relational database design and management . . . . . . . . . . . . . . . . . . . . . . . . . SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
What is ColdFusion? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Editions of ColdFusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 ColdFusion Features and Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 About the features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 About the components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 How ColdFusion Server Works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
9
10 10 10 11 11
The Development Process. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Working with ColdFusion Application Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . About applicaton pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating application pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Saving application pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Viewing application pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iv
Contents
Working with Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 About variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Adding more variables to the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Development Considerations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
..................
17
Publishing Dynamic Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Understanding Database Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Understanding Data Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 About Open Database Connectivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Accessing Data Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Adding data sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Specifying data sources dynamically . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Retrieving Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 The cfquery tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 The cfquery tag syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Writing SQL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Basic SQL syntax elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 SQL notes and considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Building Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Query notes and considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Outputting Query Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Query output notes and considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Getting Information About Query Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Query properties notes and considerations . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Using Query Results in Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Query of query benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating queries of queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Performing a query on a query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 34 34 35
.........
39
40 40 41 44 45 45 45 46 47 48
Using Forms to Specify the Data to Retrieve . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . form tag syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form notes and considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Working with Action Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Processing form variables on action pages . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamically generating SQL statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating action pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Testing for a variables existence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form variable notes and considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using HTML tables to display query results . . . . . . . . . . . . . . . . . . . . . . . . . . Formatting individual data items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Performing pattern matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Filtering data based on multiple conditions . . . . . . . . . . . . . . . . . . . . . . . . . . Creating table joins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Building flexible search interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49 50 51 51 52 52
Returning Results to the User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 If there are no query results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Returning results incrementally . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
........................
59
Creating a Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Graph types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Creating a basic graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Graphing Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Graphing a query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Graphing individual data points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Combining a query and data points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Controlling Graph Appearance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Common graph characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting bar and horizontal bar chart characteristics . . . . . . . . . . . . . . . . . . . Setting pie chart characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting line and area graph characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 62 65 66 67 67 68 71 74
.............
81
Dynamically Populating List Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Creating Dynamic Check Boxes and Multiple-Selection List Boxes. . . . . . . . . . . 84 Check boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Multiple selection lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Ensuring that Variables Exist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Using cfparam to test for variables and set default values . . . . . . . . . . . . . 88 Requiring users to enter values in form fields . . . . . . . . . . . . . . . . . . . . . . . . 89 Validating Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using cfparam to validate the data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Validating form field data types .................................... Checking query parameters with cfqueryparam . . . . . . . . . . . . . . . . . . . . . . 90 90 91 94
..............
101
5/ 9/ 01
Pa t h /Fil en a me/ Au th o r
vi
Contents
Data entry form notes and considerations . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Creating an action page to insert data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Updating Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Creating an update form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Creating an action page to update data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Deleting Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Deleting a single record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Deleting multiple records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
115
118 118 119 119 121 121 121 122 123
Array Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 About Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Structure notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 Creating and Using Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding data elements to structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Updating values in structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Getting information about structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Copying structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deleting structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Structure example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Looping through structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 127 127 128 129 130 130 130 132
..............
135
136 136 137 137 138
Creating Forms with the cfform Tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using HTML and cfform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . cfform controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Preserving input data with preservedata . . . . . . . . . . . . . . . . . . . . . . . . . . . . Browser considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Input Validation with cfform Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Validating with regular expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
vii
Input Validation with JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Handling failed validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Example: validating an e-mail address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Building Tree Controls with cftree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Grouping output from a query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . cftree form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Input validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 148 149 149
Structuring Tree Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Image names in a cftree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 Embedding URLs in a cftree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Specifying the tree item in the URL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Creating Data Grids with cfgrid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Populating a grid from a query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Creating an Updateable Grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Navigating and entering data in a grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Controlling cell contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How user edits are returned . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Editing data in cfgrid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Updating the database with cfgridupdate . . . . . . . . . . . . . . . . . . . . . . . . . . . Updating the database with cfquery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 155 156 156 157 159 160
Building Slider Bar Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Building Text Entry Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Building Drop-Down List Boxes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Embedding Java Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Registering a Java applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using cfapplet to embed an applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Handling form variables from an applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 167 169 169
......................
171
Ways to Reuse Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Reusing Common Code with cfinclude . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Using Custom Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using existing custom tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating custom CFML tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variable scopes and special variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using tag attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Passing values to and from custom tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . Passing custom tag attributes via CFML structures . . . . . . . . . . . . . . . . . . Custom tag example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 174 174 174 175 176 177 178
Nesting Custom Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Passing Data Between Nested Custom Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 What data is accessible? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
5/ 9/ 01
Pa t h /Fil en a me/ Au th o r
viii
Contents
Executing Custom Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tag instance data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modes of execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying execution modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Terminating tag execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Access to generated content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Installing Custom Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Local tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Shared tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Managing Custom Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resolving filename conflicts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Securing custom tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Encoding custom tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 188 188 189
.......
191
192 192 192 192
Debug Settings in the ColdFusion Administrator . . . . . . . . . . . . . . . . . . . . . . . . . Generating debug information for an individual page . . . . . . . . . . . . . . . . Generating debug information for an individual query . . . . . . . . . . . . . . . Error messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFML Code Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 Runtime validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 The CFML syntax checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 Troubleshooting Common Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ODBC data source configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . HTTP/URL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CFML syntax errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 195 195 195
Error Handling in ColdFusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Understanding ColdFusion errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Generating Custom Error Messages with cferror . . . . . . . . . . . . . . . . . . . . . . . . . 199 Creating an error application page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Logging Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Handling Exceptions in ColdFusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Types of recoverable exceptions supported . . . . . . . . . . . . . . . . . . . . . . . . . Exception information in cfcatch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exception handling strategies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exception handling example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Custom Exception Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 205 206 208 208 210
.....
213
Understanding the Web Application Framework. . . . . . . . . . . . . . . . . . . . . . . . . . 214 Application-level settings and functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
ix
Client, Session, Application, and Server scope variables . . . . . . . . . . . . . . 214 Custom error handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 Web server security integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 Mapping an Application Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 Processing Application.cfm and OnRequestEnd.cfm . . . . . . . . . . . . . . . . . 216 Defining the directory structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Creating the Application.cfm File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 Naming the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 Setting application default variables and constants . . . . . . . . . . . . . . . . . . 219 Managing the Client State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . About Client and Session variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . About client cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Managing client state in a clustered environment . . . . . . . . . . . . . . . . . . . Managing client state without cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 221 222 222 222
Configuring and Using Client Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Setting up Client variable options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Using Client variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Using Session Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Enabling Session variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What is a session? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Storing session data in Session variables . . . . . . . . . . . . . . . . . . . . . . . . . . . Standard Session variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Getting a list of Session variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Application Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Storing application data in Application variables . . . . . . . . . . . . . . . . . . . . Application variable timeouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tips for using Application variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Getting a list of Application variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 228 228 229 229 230 230 230 231 231 231
Using Server Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 Locking Code with cflock. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using cflock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How cflock works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using administrative lock management . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nesting locks and avoiding deadlocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 233 233 236 237
243
About CFScript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 CFScript example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Supported statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 The CFScript Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
5/ 9/ 01
Pa t h /Fil en a me/ Au th o r
Contents
Interaction of CFScript with CFML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Defining and Using Custom Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Calling functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using arguments and variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Identifying custom functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Examples of custom functons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using custom functions effectively . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 250 251 251 253 253 254
....
About Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 Basic Regular Expression Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Character classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Multicharacter Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Limiting input string size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 Anchoring a regular expression to a string . . . . . . . . . . . . . . . . . . . . . . . . . . 264 Using Backreferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 Using backreferences in replacement strings . . . . . . . . . . . . . . . . . . . . . . . 265 Returning Matched Subexpressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Regular Expression Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Regular expressions in CFML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
.........
269
Searching a ColdFusion Web Site. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 Advantages of using Verity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 Supported File Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Support for International Languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 Creating a Searchable Data Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Populating and indexing a collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Selecting an indexing method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Building a search interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indexing Query Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indexing database query results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indexing cfldap query results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indexing cfpop query results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 273 276 277 279 282 282 283 284
xi
Using Query Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simple query expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Explicit query expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Expression syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Composing search expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Searching with wildcards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Searching for special characters as literals . . . . . . . . . . . . . . . . . . . . . . . . . . Operators and modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
........
301
Using ColdFusion with Mail Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Sending E-mail Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Sending SMTP mail with cfmail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Sample Uses of cfmail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sending form-based e-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sending query-based e-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sending e-mail to multiple recipients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 304 304 305
Customizing E-mail for Multiple Recipients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Attaching a MIME file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 Advanced Sending Options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 Sending mail as HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 Error logging and undelivered messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 Receiving E-mail Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 Using cfpop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 cfpop query variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 Handling POP Mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Retrieving only message headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Retrieving an entire message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Retrieving attachments with messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deleting messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 310 312 313 314
.........
317
Using cffile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 Uploading Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Resolving conflicting filenames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321 Controlling the type of file uploaded . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321 Setting File and Directory Attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 UNIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
5/ 9/ 01
Pa t h /Fil en a me/ Au th o r
xii
Contents
Evaluating the Results of a File Upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 Moving, Renaming, Copying, and Deleting Server Files . . . . . . . . . . . . . . . . . . . . 326 Reading, Writing, and Appending to a Text File . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 Reading a text file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 Writing a text file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328 Performing Directory Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Returning file information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
......
331
Using cfhttp to Interact with the Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 Using the cfhttp Get Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 Creating a Query from a Text File. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 Using the cfhttp Post Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 Performing File Operations with cfftp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 Caching connections across multiple pages . . . . . . . . . . . . . . . . . . . . . . . . 343 Connection actions and attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 Moving Complex Data Structures Across the Web with WDDX . . . . . . . . . . . . . An overview of distributed data for the Web . . . . . . . . . . . . . . . . . . . . . . . . WDDX and Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . WDDX components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Working with application-level data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Data exchange across application servers . . . . . . . . . . . . . . . . . . . . . . . . . . . How WDDX works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 345 346 346 347 347 348
Converting CFML Data to a JavaScript Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 Transferring Data from Browser to Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 Storing Complex Data in a String. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
.................
355
ColdFusion Security Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 Remote Development Services (RDS) Security. . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 Overview of User Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 Using Advanced Security in Application Pages. . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 Using the cfauthenticate tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 Authentication and Authorization Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 Using the IsAuthenticated function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 Using the IsAuthorized function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 Catching Security Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361 Using the cfimpersonate Tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 Example of User Authentication and Authorization . . . . . . . . . . . . . . . . . . . . . . . 363
xiii
Authenticating users in Application.cfm . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 Checking for authentication and authorization . . . . . . . . . . . . . . . . . . . . . 365
.
368 368 368 368 369 369 369 370 370 370 371 371
Creating and Using COM Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 Connecting to COM objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 Setting properties and invoking methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Getting Started with CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376 Calling CORBA Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376 Declaring structures and sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376 Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 Calling Java Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Getting Started with Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java and Cold Fusion Data Type Conversions . . . . . . . . . . . . . . . . . . . . . . . Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The class loading mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A more complex Java example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 378 381 382 384 385
........
389
391 391 391 392 393 393 395 395 396 396
What Are CFX Tags?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 Before You Begin Developing CFX Tags in Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . Sample Java CFXs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting up your development environment to develop CFXs in Java . . . Customizing and Configuring Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Writing a Java CFX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Processing requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loading Java CFX classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Automatic class reloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Life cycle of Java CFXs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Calling the CFX from a ColdFusion page . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5/ 9/ 01
Pa t h /Fil en a me/ Au th o r
xiv
Contents
ZipBrowser Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 Approaches to Debugging Java CFXs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 Outputting debug information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 Using the debugging classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 Developing CFX Tags in C++. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sample C++ CFXs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting up your C++ development environment . . . . . . . . . . . . . . . . . . . . . Using the Tag Wizard to create CFXs in C++ . . . . . . . . . . . . . . . . . . . . . . . . Compiling C++ CFXs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementing C++ CFX tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Debugging C++ CFXs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 401 401 401 402 402 402
Index
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
Developing ColdFusion Applications describes the process of developing Web applications using ColdFusion. In the first eight chapters, you can follow the instructions presented to learn how to create basic ColdFusion applications. Then, chapters nine through 19 cover various topics of interest in enhancing your applications. Finally, chapters 20 through 23 explain how to extend ColdFusions capabilities. Because of the power and flexibility of ColdFusion, you can create many different types of Web applications of varying complexity. As you become more familiar with the material presented in this manual, and begin to develop your own applications, you will want to refer to the CFML Reference for details about various tags and functions.
Contents
Intended Audience................................................................................................... xvi New Features ............................................................................................................ xvi Developer Resources............................................................................................... xvii About ColdFusion Documentation ...................................................................... xviii Getting Answers .........................................................................................................xx Contacting Macromedia............................................................................................xx
xvi
Intended Audience
Developing ColdFusion Applications is intended for Web application programmers who are learning ColdFusion orwish to extended their ColdFusion programming knowledge. It provides a solid grouding in the tools that ColdFusion provides to develop Web applications. The initial chapters provide e instructions for creating a basic ColdFusion application and are intended for those who are new to ColdFusion. Later chapters cover more specific features in greater detail and are intended for both new ColdFusion programmers and for those who are looking to extend existing skill.
New Features
The following table lists the new features in ColdFusion 5: Benefit Breakthrough productivity Feature User-defined functions Query of queries Description Create reusable functions to accelerate development.
Easily integrate data from heterogeneous sources by merging and querying data in memory using standard SQL. Quickly detect and diagnose server errors with built-in server reporting and the new Log File Analyzer. Create professional-quality charts and graphs from queried data without leaving the ColdFusion environment.
Charting engine
Enhanced Verity K2 full-text Index and search up to 250,000 search documents and enjoy greater
performance.
Reporting interface for Crystal Reports 8.0
Developer Resources
xvii
Description
Take advantage of dramatically improved server performance and reduced memory usage to deliver faster, more scalable applications. Improve response time by delivering page output to users as it is built. Deliver high-performance ODBC connectivity using new drivers. Effortlessly and reliably deploy, archive, or restore entire applications using ColdFusion archive files. Keep track of server performance and availability with customizable alerts and recovery. Monitor ColdFusion applications from enterprise management systems. Deploy on additional Linux distributions, including SuSE and Cobalt. Apply optimized, agent-based support for hardware load balancers, including new support for the Cisco CSS 11000. Experience easier integration with COM components.
Expanded integration
Developer Resources
Macromedia, Inc. is committed to setting the standard for customer support in developer education, technical support, and professional services. The Web site is
xviii
designed to give you quick access to the entire range of online resources, as the following table describes. Resource Description URL
Macromedia Web General information about Macromedia www.macromedia.com/ site products and services Information on ColdFusion Technical Support ColdFusion Support Forum Detailed product information on ColdFusion and related topics Professional support programs that Macromedia offers. Access to experienced ColdFusion developers through participation in the Online Forums, where you can post messages and read replies on many subjects relating to ColdFusion. Support for installation-related issues for all Macromedia products Information about classes, on-site training, and online courses offered by Macromedia All the resources that you need to stay on the cutting edge of ColdFusion development, including online discussion groups, Knowledge Base, technical papers and more Development tips, articles, documentation, and white papers www.coldfusion.com/products/coldfusion/ www.coldfusion.com/support/ http://forums.coldfusion.com/spectraconf/
www.coldfusion.com/support/installation/ www.coldfusion.com/developer/training.cfm
www.coldfusion.com/developer/
www.coldfusion.com/developer/ coldfusionreferencedesk/
Connection with the growing network of www.coldfusion.com/partners/ solution providers, application developers, resellers, and hosting services creating solutions with ColdFusion
xix
Installing and Describes system installation and basic configuration for Configuring Windows NT, Windows 2000, Solaris, Linux, and HP-UX ColdFusion Server Advanced Describes how to connect your data sources to the ColdFusion ColdFusion Server Server, configure security for your applications, and how to use Administration ClusterCATS to manage scalability, clustering, and load-balancing for your site Developing ColdFusion Applications CFML Reference Describes on how to develop your dynamic Web applications, including retrieving and updating your data, using structures, and forms. The online-only ColdFusion Reference provides descriptions, syntax, usage, and code examples for all ColdFusion tags, functions, and variables. A brief guide that shows the syntax of ColdFusion tags, functions, and variables Describes how to use ColdFusion Studio to build, test, and deploy Web content, including using the built-in editor for a variety of scripting and markup languages
xx
Getting Answers
One of the best ways to solve particular programming problems is to tap into the vast expertise of the ColdFusion developer communities on the ColdFusion Forums. Other developers on the forum can help you figure out how to do just about anything with ColdFusion. The search facility can also help you search messages from the previous 12 months, allowing you to learn how others have solved a problem that you might be facing. The Forums is a great resource for learning ColdFusion, but it is also a great place to see the ColdFusion developer community in action.
Contacting Macromedia
Corporate headquarters
Macromedia, Inc. 600 Townsend street San Francisco, CA 4103 Tel: 415.252.2000 Fax: 415.626.0554 Web: www.macromedia.com
Technical support
Macromedia offers a range of telephone and Web-based support options. Go to http://www.coldfusion.com/ support/ for a complete description of technical support services. You can make postings to the ColdFusion Support Forum (http://forums.coldfusion.com/DevConf/index.cfm) at any time.
Sales
Toll Free: 888.939.2545 Tel: 617.219.2100 Fax: 617.219.2101 E-mail: [email protected] Web: http://commerce.coldfusion.com/purchase/ index.cfm
Chapter 1
Introduction to ColdFusion
This chapter explains the difference between creating static Web pages with HTML and creating dynamic applications with ColdFusion. It also describes what ColdFusion is and how it works.
Contents
A Quick Web Overview................................................................................................ 2 Before You Begin ......................................................................................................... 3 What is ColdFusion?.................................................................................................... 4 ColdFusion Features and Components..................................................................... 5 How ColdFusion Server Works ................................................................................... 8
HTML
You will find that ColdFusion tags (CFML) are similar in syntax to HTML tags, yet, unlike HTML, they enable you to create dynamic Web pages. You should understand how to create a basic HTML page, put information into tables, gather data in forms, and create links.
SQL
Familiarity with some SQL is helpful as you develop your ColdFusion applications. In particular, you should be able to use the SELECT, UPDATE, INSERT, and DELETE statements, as well as WHERE clauses and Boolean logic operators.
What is ColdFusion?
ColdFusion lets you create page-based Web applications using ColdFusion Markup Language (CFML), the tag-based language you use to create server-side scripts that dynamically control data integration; application logic; and user interface generation. ColdFusion Web applications can contain XML, HTML, and other client technologies such as CSS and JavaScript. ColdFusion application pages are different from static HTML pages in the following ways: They are saved and referenced with a specific file extension. The default ColdFusion file extension is cfm. They contain ColdFusion Markup Language.
Editions of ColdFusion
There are two editions of ColdFusion: Enterprise and Professional. Using ColdFusion Enterprise or Professional Edition and ColdFusion Studio, you can build Web applications that leverage existing technologies and business systems such as RDBMS, messaging servers, file repositories, directory servers, and distributed object middleware. ColdFusion Enterprise also offers advanced security features, load balancing, server failover, and visual cluster administration.
Scalable deployment
Benefits
Features
Open integration Database connectivity using native database drivers (Enterprise Edition only), ODBC, or OLE DB Embedded support for full-text indexing and searching Standards-based integration with directory, mail, HTTP, FTP, and file servers Connectivity to distributed object technologies, including CORBA (Enterprise Edition only), COM (Windows Enterprise Edition only), Java objects and EJBs Open extensibility with C/C++ and Java Security Integration with existing authentication systems, including Windows NT domain and LDAP directory servers, and proprietary user and group databases Advanced access control so that server administrators can control developers access to files and data sources Support for existing database security Server sandbox security for protecting multiple applications on a single server (Enterprise Edition only) Support for existing Web server authentication, security, and encryption
For detailed information about security, see Advanced ColdFusion Administration. For the latest publications from Macromedia on security, visit the Security Zone at http://www.coldfusion.com/developer/securityzone/. For a complete feature list and more detailed information, see the ColdFusion product pages at http://www.coldfusion.com/coldfusion.
data input and format data output. They can contain ColdFusion (CFML) tags, HTML tags, CFScript, JavaScript, and anything else that you can normally embed in an ordinary HTML page. You can easily access data sources, such as relational databases, from your application pages. The default file extension used for ColdFusion application pages is cfm.
CFML
CFML is a tag-based server scripting language that encapsulates complex processes, such as connecting to databases and LDAP servers, and sending e-mail. The core of the ColdFusion development platform language is more than 70 server-side tags and more than 200 functions.
ColdFusion Server
ColdFusion Server listens for requests from the Web server to process ColdFusion application pages. It runs as a service under Windows NT and as a process under UNIX. For information on installing and configuring ColdFusion Server, see Installing and Configuring ColdFusion Server.
ColdFusion Administrator
You use the Administrator to configure various ColdFusion Server options, including: ColdFusion data sources Debugging output Server settings Application security Server clustering Scheduling page execution Directory mapping For details on using the Administrator, see Advanced ColdFusion Administration.
Data sources
ColdFusion applications can interact with any database that supports the ODBC standard. However, ColdFusion is not limited to ODBC data sources. You can also retrieve data using OLE-DB, native database drivers, or directory servers that support the Lightweight Directory Access Protocol (LDAP). You can also retrieve data from mail servers that support the Post Office Protocol (POP), and index the data in Verity collections.
Chapter 2
This chapter guides you through the ColdFusion development process as you create a ColdFusion application page, save it, and view it in a browser.
Contents
The Development Process........................................................................................ 10 Working with ColdFusion Application Pages.......................................................... 10 Working with Variables ............................................................................................. 13 Development Considerations .................................................................................. 16
10
11
<!--- Set all variables ---> <cfset department="Sales"> <!--- Display results ---> <cfoutput> Id like to talk to someone in #Department#. </cfoutput> </body> </html>
12
Compare the code that was returned to the browser with what you originally created. Notice that the ColdFusion comments and CFML tags are processed, but do not appear in the HTML file that is returned to the browser. Original ColdFusion page
<html> <head> <title>Call Department</title> </head> <body> <strong>Call Department</strong><br> <!--- Set all variables ---> <cfset department="Sales"> <!--- Display results ---> <cfoutput> Id like to talk to someone in #Department#. </cfoutput> </body> </html>
Description CFML comment, which is not returned in the HTML page. Creates a variable named Department and sets the value equal to Sales. CFML comment, which is not returned in the HTML page. Displays whatever appears between the opening and closing cfoutput tags; in this example, the text I'd like to talk to someone in is followed by the value of the variable Department, which is Sales.
<cfset Department="Sales">
13
About variables
ColdFusion variable names are case-insensitive. The variable names CITY and city refer to the same data. The kind of information that variables contain varies. Two characteristics distinguish the information in a variable: Data type Scope type
Data types
A variables data type specifies the kind of value a variable can represent, such as a text string or number. ColdFusion does not require you to specify a variables data type. Whether a variable represents a string, a number, a Boolean value (Yes/No), a date and time, or a more complex object such as an array or structure, ColdFusion automatically uses the appropriate internal data representation when you assign its value. However, ColdFusion does provide methods to examine and change the type of data that a variable represents. For a complete list of data types see the CFML Reference. For example, use the following syntax to create a string variable:
<cfset mystring="Hello world">
The following example uses scientific notation to create a floating-point numeric variable:
<cfset myfloat=1.296e-3>
Scope types
Variables differ in the source the data came from, the places in your code where they are meaningful, and how long their values persist. These considerations are generally referred to as a variables scope. ColdFusion has many different scope types, which are identified by prefixes to a variable name. For example, the variable Department in calldept.cfm is a local variable (a variable that has meaning on the current page). Local variables have the optional prefix Variables. Instead of writing:
Id like to talk to someone in #Department#.
14
Some variable scopes, such as the local scope, do not require the scope identifier prefix, while others do. However, it is good programming practice to use prefixes for most or all scopes. This helps to better identify each variables use and can prevent multiple uses of the same name. This book uses the scope prefix for all variables except for local variables. The following table lists some of the more common types of variable scopes and the prefixes that you use to identify the variables. Other chapters in this book discuss additional scope types. The CFML Reference has a complete list of scope types, their identifiers, and how they are used. Scope type Local (or Variables) Prefix Variables Description Variables created using cfset or cfparam, with or without specifying the scope prefix. You must define the variable on the current page or a page you include using cfinclude. Data entered in tags in an HTML form or ColdFusion
cfform tag block and processed on an action page.
Form URL
Form URL
Note
Remember that ColdFusion cannot interpret anything, including variables, that is not inside a ColdFusion tag or tag block. The following table illustrates the basic use of pound signs. For a detailed description of the use of pound signs, see CFML Reference. CFML code
cfset Department="Sales">
Results The variable named Department is created and the value is set to Sales. ColdFusion does not treat Department as a variable because it is not surrounded by pound signs. The HTML page displays: Id like to talk to someone in Department.
15
CFML code
<cfoutput> Id like to talk to someone in #Department#. </cfoutput> <cfoutput> The department name spelled backward is Reverse(Department). </cfoutput>
Results ColdFusion replaces the variable Department with its value. The HTML page displays: Id like to talk to someone in Sales. ColdFusion sees Reverse(Department) as text and displays it unchanged. The HTML page displays: The department name spelled backward is Reverse(Department). ColdFusion uses the Reverse function to reverse the text in the Department variable and displays the result. The pound signs tell cfoutput to interpret Reverse as a ColdFusion function. The Reverse function uses the Department variable name. The HTML page displays: The department name spelled backward is selaS.
16
View the page in your Web browser by entering the following URL:
http://127.0.0.1/myapps/calldept.cfm.
Development Considerations
The same development rules that apply for any programming environment apply to ColdFusion. You should also follow the same programming conventions that you would with any other language: Comment your code as you go. HTML comments use this syntax: <!-- html comment --> CFML comments add an extra dash: <!--- cfml comment ---> ColdFusion removes CFML comments from the HTML that it sends to the browser, so users do not see them if they view the HTML source. ColdFusion does send HTML comments to the browser. Filenames should be all one word, begin with a letter, and can contain only letters, numbers, and the underscore. Filenames should not contain special characters. Some operating systems are case-sensitive, so you should be consistent with your use of capital letters in filenames.
Chapter 3
Querying a Database
This chapter describes how to retrieve data from a database, work with query data, and enable debugging in ColdFusion applications. You will learn how to use the ColdFusion Administrator to set up a data source and enable debugging, use the cfquery tag to query a data source, and use the cfoutput tag to output the query results to a Web page.
Contents
Publishing Dynamic Data......................................................................................... 18 Understanding Database Basics .............................................................................. 19 Understanding Data Sources ................................................................................... 20 Accessing Data Sources ............................................................................................ 21 Retrieving Data .......................................................................................................... 25 Writing SQL................................................................................................................ 26 Building Queries........................................................................................................ 28 Outputting Query Data ............................................................................................. 30 Getting Information About Query Results .............................................................. 32 Using Query Results in Queries................................................................................ 34
18
19
You can organize data in multiple tables. This type of data structure is known as a relational database and is the type used for all but the simplest data sets.
20
21
Borland dBase-compliant databases Microsoft Excel worksheet data ranges Borland Paradox Databases Informix databases Progress databases Oracle 8 databases Centura SQLBase databases Sybase ASE databases Delimited text files
You can also use any additional ODBC drivers that are installed on your system. On UNIX, look in the ODBC page of the ColdFusion Administrator for a list of available ODBC drivers. A good source of information on ODBC is the ODBC Programmers Reference at http:/ /www.microsoft.com/data/odbc.
22
When you add a data source, you assign it a name so that you can reference it within tags such as cfquery on application pages to query databases. During a query, the data source tells ColdFusion which database to connect to and what parameters to use for the connection. Use the following procedure to add the CompanyInfo data source that you use in many examples in this book. Note By default, the ColdFusion setup installs the CompanyInfo and cfsnippets databases used in examples in this book and adds them to the available ODBC data sources. Therefore, this procedure should not be necessary to work with examples in this book.
23
4 5 6 7
Name the data source CompanyInfo. On Windows Select Microsoft Access Driver (*.mdb) from the drop-down box to describe the ODBC driver. On UNIX, select the Merant Dbase/FoxPro driver. Click Add. In the Database File field, enter the full path of the database. (You can also use the Browse button to locate the file.). On Windows specify the path to the company.mdb file, typically C:\CFusion\database\Company.mdb. On UNIX, specify the path to the CompanyInfo directory, typically /opt/coldfusion/database/CompanyInfo.
8 9
Click Create to create the CompanyInfo data source. The data source is added to the data source list. Locate CompanyInfo in the data source list. If the data source was created, you should see this message:
The connection to the data source was verified successfully.
11 Click Go Back to return to the data sources list. For more information about managing data sources, see Advanced ColdFusion Administration.
Note Connect string properties are specific to the database you are connecting to. See the documentation for your database for a list of connect string properties.
24
Specify all the required ODBC connection information, including the ODBC driver and the database location, in the connectstring attribute. For example, you could use the following code for a query that dynamically specifies the pubs database on a local Microsoft SQLServer:
<cfquery name = "datelist" dbtype = "dynamic" blockfactor = 100 connectstring = "DRIVER={SQLSERVER};SERVER=(local);UID=sa;PWD=; DATABASE=pubs"> SELECT * FROM authors </cfquery>
Retrieving Data
25
Retrieving Data
You can query databases to retrieve data at runtime. The retrieved data, called the result set, is stored on that page as a query object. When retrieving data from a database, perform the following tasks: Use the cfquery tag on a page to tell ColdFusion how to connect to a database. Write SQL commands inside the cfquery block to specify the data that you want to retrieve from the database. Later on the page, reference the query object and use its data values in any tag that presents data, such as cfoutput, cfgrid, cftable, cfgraph, or cftree.
In this example, the query code tells ColdFusion to: Use the CompanyInfo data source to connect to the company.mdb database. Store the retrieved data in the query object EmpList. Follow these rules when creating a cfquery tag: The cfquery tag is a block tag, that is, it has an opening <cfquery> and ending </cfquery> tag. Use the name attribute to name the query object so that you can reference it later on the page. Use the datasource attribute to name an existing data source that should be used to connect to a specific database. Alternatively, use the dbtype = "dynamic" and connectString attributes to dynamically specify a database. Always surround attribute values with double quotes ("). Place SQL statements inside the cfquery block to tell the database what to process during the query.
26
When referencing text literals in SQL, use single quotes (). For example, Select * from mytable WHERE FirstName=Russ selects every record from mytable in which the first name is Russ.
Writing SQL
In between the begin and end cfquery tags, write the SQL that you want the database to execute. For example, to retrieve data from a database: Write a SELECT statement that lists the fields or columns that you want to select for the query. Follow the SELECT statement with a FROM clause that specifies the database tables that contain the columns. Tip If you are using ColdFusion Studio, you can use the Query Builder to build SQL statements by graphically selecting the tables and records within those tables that you want to retrieve. When the database processes the SQL, it creates a data set (a structure containing the requested data) that is returned to ColdFusion Server. ColdFusion places the data set in memory and assigns it the name that you defined for the query in the name attribute of the cfquery tag. You can reference that data set by name using the cfoutput tag later on the page.
Statements
A SQL statement always begins with a SQL verb. The following keywords identify commonly used SQL verbs: Keyword SELECT INSERT UPDATEw DELETE Description Retrieves the specified records Adds a new row Changes values in the specified rows Removes the specified rows
Writing SQL
27
Statement clauses
Use the following keywords to refine SQL statements: Keyword FROM WHERE ORDER BY GROUP BY Description Names the data tables for the operation Sets one or more conditions for the operation Sorts the result set in the specified order Groups the result set by the specified select list items
Operators
The following basic operators specify conditions and perform logical and numeric functions: Operator AND OR NOT LIKE IN BETWEEN = <> < > <= >= + / * Description Both conditions must be met At least one condition must be met Exclude the condition following Matches with a pattern Matches with a list of values Matches with a range of values Equal to Not equal to Less than Greater than Less than or equal to Greater than or equal to Addition Subtraction Division Multiplication
28
Some DBMS vendors use nonstandard SQL syntax (known as a dialect) in their products. ColdFusion does not validate the SQL in a cfquery, so you are free to use any syntax that is supported by your data source. Check your DBMS documentation for nonstandard SQL usage.
Building Queries
As discussed earlier in this chapter, you build queries using the cfquery tag and SQL.
Save the page as emplist.cfm in myapps under the Web root directory. For example, the directory path on your machine might be: C:\INETPUB\WWWROOT\myapps on Windows NT Return to your browser and enter the following URL to view EmpList.cfm:
http://127.0.0.1/myapps/emplist.cfm
4 5
View the source in the browser. The ColdFusion Server creates the EmpList data set, but only HTML and text is sent back to the browser so you just see the heading Employee List. To display the data set on the page, you must code tags and variables to output the data.
Building Queries
29
Description Queries the database specified in the CompanyInfo data source Gets information from the FirstName, LastName, Salary, and Contract fields in the Employee table Ends the cfquery block
30
3 4
Save the file as emplist.cfm. View the page in a browser. A list of employees appears in the browser, with each line displaying one row of data.
You created a ColdFusion application page that retrieves and displays data from a database. At present, the output is raw. You will learn how to format the data in the next chapter.
31
You now display the results of the query on the page. The following table describes the code and its function: Code
<cfoutput query="EmpList">
Description Display information retrieved in the EmpList query. Display information for each record in the query, until you run out of records. Display the value of the FirstName, LastName, Salary, Contract fields of each record, separated by commas and spaces. Insert a line break (go to the next line) after each record. End the cfoutput block.
32
3 4
The number of employees now appears below the list of employees. Note The variable cfquery.executionTime contains the amount of time, in milliseconds, it took for the query to complete. Do not prefix the variable name with the query name.
33
You now display the number of records retrieved in the query. The following table describes the code and its function: Code
<cfoutput> The query returned #EmpList.RecordCount# records </cfoutput>
Description Display what follows Display the text The query returned Display the number of records retrieved in the EmpList query Display the text records End the cfoutput block.
34
35
Boolean predicates:
LIKE NOT LIKE IN NOT IN BETWEEN NOT BETWEEN AND OR
Aggregate functions:
Count([DISTINCT][*] expr) Sum([DISTINCT] expr) Avg([DISTINCT] expr) Max(expr) Min(expr)
Comparison operators:
<= >= = < > <>
You can also do the following tasks: Use the results of one or two queries in your SQL statement. Generate computed columns.
36
3 4
Save the page as queryquery.cfm in myapps under the Web root directory. Return to your browser and enter the following URL to view the results of the query: http://127.0.0.1/myapps/queryquery.cfm View the source in the browser.
37
Description Set the last name to use in the second query. In a complete application, this information comes from user interaction. Query the database specified in the CompanyInfo data source and select all data in the Employee table. Cache the query data between requests to this page, and do not query the database if the cached data is less than an hour old. Use the EmpList query as the source of the data in a new query. This query selects only entries that match the last name specified by the LastNameSearch variable. The query also selects only three columns of data: employee ID, first name, and last name. Use the QueryFromQuery query to display the list of employee IDs, first names, and last names.
<cfquery datasource = "CompanyInfo" name = "EmpList" cachedwithin=#CreateTimeSpan(0,1,0,0 )#> SELECT * FROM Employee </cfquery> <cfquery dbtype = "query" name = "QueryFromQuery" > SELECT Emp_ID, FirstName, LastName FROM Emplist WHERE LastName=#LastNameSearch# </cfquery> <cfoutput query = QueryFromQuery> #Emp_ID#: #FirstName# #LastName#<br> </cfoutput> <br> <cfoutput> #EmpList.columnlist#<br> </cfoutput> <cfoutput> #QueryFromQuery.columnlist#<br> </cfoutput>
List all the columns returned by the Emplist query. List all the columns returned by the QueryFromQuery query.
38
Chapter 4
This chapter explains how to select the data to display in a dynamic Web page. It also describes how to populate an HTML table with query results and how to use ColdFusion functions to format and manipulate data.
Contents
Using Forms to Specify the Data to Retrieve........................................................... 40 Working with Action Pages ....................................................................................... 45 Working with Queries and Data ............................................................................... 49 Returning Results to the User................................................................................... 55
40
Note
Because forms are standard HTML, the syntax and examples that follow provide you with just enough detail to begin using ColdFusion.
Attribute
action
Description Specifies an action page to which you pass form variables for processing. Specifies how the variables are submitted from the browser to the action page on the server. All ColdFusion forms must be submitted with an attribute setting of method=post
method
You can override the server request timeout (set on the ColdFusion Administrator Server Settings page) by adding a RequestTimeout parameter to the action page URL. The following example specifies a request timeout of two minutes:
41
Form controls
Within the form, you describe the form controls needed to gather and submit user input. There are a variety of form controls types available. You choose form control input types based on the type of input the user should provide.
The following table illustrates the format of form control tags: Control Text control Radio buttons Code
<input type="Text" name="ControlName" size="Value" maxlength="Value"> <input type="Radio" name="ControlName" value="Value1">DisplayName1 <input type="Radio" name="ControlName" value="Value2">DisplayName2 <input type="Radio" name="ControlName" value="Value3">DisplayName3
List box
Check box
42
Code
<input type="Reset" name="ControlName" value="DisplayName"> <input type="Submit" name="ControlName" value="DisplayName">
To create a form
1 2 Create a new application page, using ColdFusion Studio. Edit the page so that it appears as follows:
<html> <head> <title>Input form</title> </head> <body> <!--- define the action page in the form tag. The form variables will pass to this page when the form is submitted ---> <form action="actionpage.cfm" method="post"> <!-- text box --> <p> First Name: <input type="Text" name="FirstName" size="20" maxlength="35"><br> Last Name: <input type="Text" name="LastName" size="20" maxlength="35"><br> Salary: <input type="Text" name="Salary" size="10" maxlength="10"> </p> <!-- list box --> <p> City <select name="City"> <option value="Arlington">Arlington <option value="Boston">Boston <option value="Cambridge">Cambridge <option value="Minneapolis">Minneapolis <option value="Seattle">Seattle </select> </p> <!-- radio buttons --> <p> Department:<br> <input type="radio" name="Department" value="Training">Training<br> <input type="radio" name="Department" value="Sales">Sales<br> <input type="radio" name="Department" value="Marketing">Marketing<br> </p>
43
<!-- check box --> <p> Contractor? <input type="checkbox" name="Contractor" value="Yes" checked>Yes </p> <!-- reset button --> <input type="Reset" name="ResetForm" value="Clear Form"> <!-- submit button --> <input type="Submit" name="SubmitForm" value="Submit"> </form> </body> </html>
3 4
Save the page as formpage.cfm within the myapps directory under your Web root directory. View the form in a browser. The form appears in the browser. Remember that you need an action page in order to submit values; you will create one later in this chapter.
Description Gather the information from this form using the Post method, and do something with it on the page actionpage.cfm.
<input type="Text" name="FirstName" Create a text box called FirstName where size="20" maxlength="35"> users can enter their first name. Make it
Create a text box called LastName where users can enter their first name. Make it 20 characters wide, but allow input of up to 35 characters. Create a text box called Salary where users can enter a salary to look for. Make it 10 characters wide, and allow input of up to 10 characters.
44
Code
<select name="City"> <option value="Arlington"> Arlington <option value="Boston">Boston <option value="Cambridge"> Cambridge <option value="Minneapolis"> Minneapolis <option value="Seattle">Seattle </select> <input type="checkbox" name= "Contractor" value="Yes|No" checked>Yes
Description Create a drop-down list box named City and populate it with the values Arlington, Boston, Cambridge, Minneapolis, and Seattle.
Create a check box that allows users to specify whether they want to list employees who are contractors. Make the box selected by default. Create a reset button to allow users to clear the form. Put the text Clear Form on the button. Create a submit button to send the values that users enter to the action page for processing. Put the text Submit on the button.
45
Note
If multiple controls have the same name, one form variable is passed to the action page. It contains a comma-delimited list. A form variables name is the name that you assigned to the form control on the form page. Refer to the form variable by name within tags, functions, and other expressions on an action page. Because Form variables extend beyond the local pagetheir scope is the action pageprefix them with Form. to explicitly tell ColdFusion that you are referring to a form variable. For example the following code references the LastName form variable for output on an action page:
<cfoutput> #Form.LastName# </cfoutput>
But when you want to return information about employees that match user search criteria, you use the SQL WHERE clause with a SQL SELECT statement to compare a value against a character string field. When the WHERE clause is processed, it filters the query data based on the results of the comparison. For example, to return employee data for only employees with the last name of Smith, you build a query that looks like this:
<cfquery name="GetEmployees" datasource="CompanyInfo"> SELECT FirstName, LastName, Contract FROM Employee WHERE LastName = "Smith" </cfquery>
46
However, instead of putting the LastName directly in the SQL WHERE clause, you can use the text that the user entered in the form for comparison:
<cfquery name="GetEmployees" datasource="CompanyInfo"> SELECT FirstName, LastName, Salary FROM Employee WHERE LastName="#Form.LastName#" </cfquery>
For more information on Dynamic SQL, see Dynamic SQL on page 96.
3 4 5
Save the page as actionpage.cfm within the myapps directory. View formpage.cfm in your browser. Enter data, for example, Smith, in the Last Name box and submit the form. The browser displays a line with the first and last name and salary for each entry in the database that match the name you typed, followed by a line with the text Contractor: Yes
6 7
Click Return in your browser to redisplay the form. Remove the check mark from the check box and submit the form again.
47
This time an error occurs because the check box does not pass a variable to the action page.
Description Query the data source CompanyInfo and name the query GetEmployees. Retrieve the FirstName, LastName, and Salary fields from the Employee table, but only if the value of the LastName field matches what the user entered in the LastName text box in the form on formpage.cfm. Display results of the GetEmployees query. Display the value of the FirstName, LastName, and Salary fields for a record, starting with the first record, then go to the next line. Keep displaying the records that match the criteria you specified in the SELECT statement, followed by a line break, until you run out of records. Close the cfoutput block. Display a blank line followed by the text Contractor: and the value of the form Contractor check box. A more complete example would test to ensure the existence of the variable and would use the variable in the query.
</cfif>
48
The argument passed to the IsDefined function must always be enclosed in double quotes. For more information on the IsDefined function, see the CFML Reference. If you attempt to evaluate a variable that you did not define, ColdFusion cannot process the page and displays an error message. To help diagnose such problems, use the interactive debugger in ColdFusion Studio or turn on debugging in the ColdFusion Administrator. The Administrator debugging information shows which variables are being passed to your application pages.
49
50
</body> </html>
3 4 5 6
Save the page as actionpage.cfm within the myapps directory. View formpage.cfm in your browser. Enter Smith in the Last Name text box and submit the form. The records that match the criteria specified in the form appear in a table.
Description Put data into a table. In the first row of the table, include three columns, with the headings: First Name, Last Name, and Salary. Get ready to display the results of the GetEmployees query. Create a new row in the table, with three columns. For a record, put the value of the FirstName field, the value of the LastName field, and the value of the Salary field. Keep getting records that matches the criteria, and display each row in a new table row until you run out of records. End of table.
</table>
to
<td>#DollarFormat(Salary)#</td>
51
The LIKE operator tells the database to use the string that follows for pattern matching. If you place a wildcard before and after AL, you retrieve any record in that column that contains AL. Surround strings in SQL statements with single quotes (). To return information from the Departmt table on all departments except the sales department, you would build a query that looks like this:
<cfquery name="GetDepartments" datasource="CompanyInfo"> SELECT * FROM Departmt WHERE Dept_Name NOT LIKE [Ss]ales </cfquery>
The first character in the match can be either upper case S or lower case s.
Note
Whether SQL identifiers and data comparison operations are case sensitive depends on the database.
52
It ensures that each row of the query results contains the department name from the Departmt table that corresponds to the Department ID in this employees row in the Employee table. Without this statement, the query returns a row for every employee in the Employee table, and all rows have the Dept_Name HR, even if the employee is not in the HR department. When you do table joins, keep the following information in mind: Prefix each column in the SELECT statement to explicitly state which table the data should be retrieved from. In this example, the Dept_ID field is the primary key of the Departmt table and the foreign Key of the Employee table. A foreign key uniquely identifies another record (in this example, a record in the Departmt table) but does not uniquely identify the current record (in the Employee table).
53
The following action page allows users to search for employees by department, last name, or both.
3 4 5
Save the file. View formpage.cfm in your browser. Select a department, optionally enter a last name, and submit the form.
54
Description Retrieve the fields listed from the Departmt and Employee tables, joining the tables based on the Dept_ID field in each table.
If the user specified a department on the form, only retrieve records where the department name is the same as the one the user specified. Note that you need the pound signs in the SQL AND statement to identify Form.Department as a ColdFusion variable, but not in the IsDefined function. If the user specified a last name in the form, only retrieve the records in which the last name is the same as the one the user entered in the form.
55
You mst do the following: Prefix RecordCount with the query name. Add a procedure after the cfif tag that displays a message to the user. Add a procedure after the cfelse tag to format the returned data. Follow the second procedure with a </cfif> tag end to indicate the end of the conditional code.
56
<cfif form.lastname is not ""> AND Employee.LastName = #Form.LastName# </cfif> </cfquery> <cfif GetEmployees.recordcount is "0"> No records match your search criteria. <br> Please go back to the form and try again. <cfelse> <h4>Employee Data Based on Criteria from Form</h4> <table> <tr> <th>First Name</th> <th>Last Name</th> <th>Salary</th> </tr> <cfoutput query="GetEmployees"> <tr> <td>#FirstName#</td> <td>#LastName#</td> <td>#Salary#</td> </tr> </cfoutput> </cfif> </table> </body> </html>
3 4 5
Save the file. Return to the form, enter search criteria and submit the form. If no records match the criteria you specified, the message displays.
57
When you flush data, make sure that a sufficient amount of information is available, because some browsers might not respond if you flush only a very small amount. Similarly, if you use an interval attribute, set it for a reasonable size, such as a few hundred bytes or more but not many thousands of bytes.
Caution
After you use the cfflush tag on a page, any CFML function or tag on the page that modifies the HTML header causes an error. These include the cfcontent, cfcookie, cfform, cfheader, cfhtmlhead, and cflocation tags. You also get an error if you use the cfset tag to set a Cookie scope variable. All errors except Cookie errors can be caught with a cfcatch type="template" tag. Cookie errors can be caught with cfcatch type="Any". The following example uses the cfloop tag and the rand() random number generating function to artificially delay the generation of data for display. It simulates a situation in which it takes time to retrieve the first data and additional information becomes available slowly.
<html> <head> <title>Your Magic numbers</title> </head> <body> <H1>Your Magic numbers</H1> <P>It will take us a little while to calculate your ten magic numbers. It takes a lot of work to find numbers that truly fit your personality. So relax for a minute or so while we do the hard work for you.</P> <H2>We are sure you will agree it was worth the short wait!</H2> <cfflush> <cfflush interval=10> <!--- Delay Loop to make is seem harder ---> <cfloop index="randomindex" from="1" to="200000" step="1"> <cfset random=rand()> </cfloop> <!--- Now slowly output 10 random numbers ---> <cfloop index="Myindex" from="1" to="10" step="1"> <cfloop index="randomindex" from="1" to="100000" step="1"> <cfset random=rand()> </cfloop> <cfoutput> Magic number number #Myindex# is: #RandRange( 100000, 999999)#<br><br> </cfoutput> </cfloop> </body> </html>
58
Description Send the HTML header and all HTML output to the cfflush tag to the user. This displays the explanatory paragraph and H2 tag contents. Flush additional data to the user every time at least ten bytes are available. Insert an artificial delay by using the Rand function to calculate many random numbers. Generate and display ten random numbers. This code uses two loops. The outer loop is repeated ten times, once for each number to display. The inner loop uses the rand function to create another delay by generating more (unused) random numbers. It then calls the RandRange function to generate a six-digit random number for display.
<cfflush interval=10>
<cfloop index="randomindex" from="1" to="200000" step="1"> <cfset random=Rand()> </cfloop> <cfloop index="Myindex" from="1" to="10" step="1"> <cfloop index="randomindex" from="1" to="100000" step="1"> <cfset random=rand()> </cfloop> <cfoutput> Magic number number #Myindex# is: #RandRange (100000,999999)#<br><br> </cfoutput> </cfloop>
Chapter 5
Graphing Data
This chapter explains how to use the cfgraph tag to display graphs. It illustrates ways that you can graph data and gives you the tools you need to create effective graphs. The cfgraph tag requires the JRun server and the Macromedia Generator server, which install with ColdFusion.
Contents
Creating a Graph ....................................................................................................... 60 Graphing Data ........................................................................................................... 62 Controlling Graph Appearance ................................................................................ 67 Linking Dynamically from Graphs........................................................................... 77
60
Creating a Graph
The cfgraph tag provides five graph types. A large number of attributes let you customize the graph appearance to meet your needs.
Graph types
You can create the following types of graphs: Bar Horizontal bar Line Area (a line graph with the area below the line filled in) Pie The following illustrations show one sample of each type of graph:
Creating a Graph
61
You must end your cfgraph tag with a </cfgraph> end tag. For example, if you have a query that contains average salary by department, the following tag displays a bar graph with the information:
<cfgraph type="bar" query="DataTable" valueColumn="AvgByDept" itemColumn="Dept_Name"> </cfgraph>
Later sections in this chapter provide information on how you can specify the data differently and how you can change and enhance graph appearance.
62
Graphing Data
One of the most important considerations when you graph data is the way you supply the data to the cfgraph tag. You can supply data in several ways: Provide all the data in a single query. Specify individual data points using cfgraphdata tags. Combine data from a query with additional data points from cfgraphdata tags. Note The cfgraph tag graphs numeric data only. As a result, you must convert any dates, times, or preformatted currency values, such as $3,000.53, to integers or real numbers.
Graphing a query
When you graph a query, you specify the query name in the cfgraph tag query attribute. In this format the cfgraph tag body is empty. However, you must still provide the <\cfgraph> end tag. For example, a simple cfgraph tag for a bar chart might look like this:
<cfgraph type="bar" title="Salaries by Department" query="DataTable" itemColumn="Dept_Name" valueColumn="AvgByDept"> </cfgraph>
This tag displays the values in the AvgByDept column of the DataTable query. It displays the Dept_Name column value as the item label by each bar. The title Salaries by Department appears above the chart. The cfgraph tag can take the following information from a query: Attribute query valueColumn itemColumn Description The query containing the data. The query column containing the values to be graphed. (Optional) The query column containing the description for this data point. The item normally appears on the horizontal axis of bar and line graphs, on the vertical axis of horizontal bar graphs, and in the legend in pie charts.
Graphing Data
63
Attribute URL
Description (Optional) Works only with bar, horizontal bar, and pie charts in Flash file format. A static prefix for all data point URLs. When the user clicks a bar or pie wedge, the page links to a URL created by appending the data from the data points URLColumn value. Use this attribute to specify a string that is part of all links on a chart, such as http://www.mycompany.com/myapp/salary_info/chart_details/. (Optional) Works only with bar, horizontal bar, and pie charts in Flash file format. The query column containing the data pointspecific part of a URL to load when the user clicks the corresponding data point the graph. ColdFusion encodes the contents of the query field, in URL format (for example, replacing space characters with %20) and appends it to any static URL string in the URL attribute to create a full URL link. Use this attribute to do data drill-down from your charts. For more information on using URLs in graphs, see Linking Dynamically from Graphs, on page 77.
URLColumn
The ability to use queries of queries, as described in Chapter 3, Using Query Results in Queries on page 34 provides significant power in generating the data for the chart. For example, you can use aggregating clauses operators such as SUM, AVG, and GROUP BY to create a query of queries with statistical data based on a raw database query. You can also take advantage of the ability to reference and modify query data dynamically. For example, you can loop through the entries in a query column and reformat the data to show whole dollar values
64
<!-- Generate a query with statistical data for each department. --> <cfquery dbtype = "query" name = "DeptSalaries"> SELECT Dept_Name, AVG(Salary) AS AvgByDept FROM GetSalaries GROUP BY Dept_Name </cfquery> <!--- Reformat the generated numbers to show only thousands ---> <cfloop index="i" from="1" to="#DeptSalaries.RecordCount#"> <cfset DeptSalaries.AvgByDept[i]=Round(DeptSalaries.AvgByDept[i]/ 1000)*1000> </cfloop> <html> <head> <title>Employee Salary Analysis</title> </head> <body> <h1>Employee Salary Analysis</h1> <!--- Bar graph, from DeptSalaries Query of Queries ---> <cfgraph type="bar" query="DeptSalaries" valueColumn="AvgByDept" itemColumn="Dept_Name"> </cfgraph> <br> </body> </html>
Save the page as graphdata.cfm in myapps under the Web root directory. For example, the directory path on your machine might be: C:\Inetpub\wwwroot\myapps on Windows NT Return to your browser and enter the following URL to view graphdata.cfm: http://127.0.0.1/myapps/graphdata.cfm
Graphing Data
65
Description Query the CompanyInfo database to get the Dept_Name and Salary for each employee. Because the Dept_Name is in the Departmt table and the Salary is in the Employee table, you need a table join in the WHERE clause. The raw results of this query could be used elsewhere on the page. Generate a new query from the GetSalaries query. Use the AVG aggregating function to get statistical data on the employees. Use the GROUP BY statement to ensure that there is only one row for each department. Loop through all the rows in DeptSalaries query and round the salary data to the nearest thousand. This loop uses the query variable RecordCount to get the number of rows and changes the contents of the query object directly. Create a bar graph using the data from the AvgByDept column of the DeptSalaries query. Label the bars with the Department names.
<cfquery dbtype = "query" name = "DeptSalaries"> SELECT Dept_Name, AVG(Salary) AS AvgByDept FROM GetSalaries GROUP BY Dept_Name </cfquery> <cfloop index="i" from="1" to="#DeptSalaries.RecordCount#"> <cfset DeptSalaries.AvgByDept[i]= Round(DeptSalaries.AvgByDept[i] /1000)*1000> </cfloop>
66
This pie chart displays the income values of four departments. Each cfgraph tag specifies a departments income and the corresponding item description for the legend. The values are specified by individual ColdFusion variables. The title Income by Department appears above the chart. The cfgraphdata tag lets you specify the following information about a data point: Attribute value item Description The data value to be graphed. (Optional) The description for this data point. The item normally appears on the horizontal axis of bar and line graphs, on the vertical axis of horizontal bar graphs, and in the legend in pie charts. (Optional) The color of the bar or pie slice. Ignored for line and area graphs. (Optional) Works only with bar, horizontal bar, and pie charts in Flash file format. A URL to load when the user clicks this data point. Use this attribute to do data drill-down from your charts. For more information on using URLs in graphs, see Linking Dynamically from Graphs, on page 77.
color URL
67
Description The title to display on the graph and the font to use. Whether to send the graph to the user as a jpeg or Flash (.swf) file. Flash is the default format. On pie and bar charts, Flash supports rollover display of data values and data drill-down by clicking on the data point (using the URLColumn attribute). The width and height in pixels of the graph. This size defines the entire graph area, including the legend and background area around the graph. You cannot use these attributes to change the ratio of the data area height to width. For example, you cannot set a large graphWidth value to stretch just the horizontal dimension. To change the overall graph size, specify both the graphHeight and graphWidth. The background color to use for the entire graph area, including legends and margins. You can specify any of the standard 256 Web colors. You can use any valid HTML color format. If you use the numeric format, you must use double pound signs, for example, ##CCFFFF. The border that surrounds the graph. You specify the width in pixels and the color using any valid HTML color format, as described for the backgroundColor. A value of 0 means no border. The depth of the shading that gives the graph three-dimensional appearance, in pixels. A value of 0 (the default) means no 3D appearance.
Dimensions
graphWidth graphHeight
Background
backgroundColor
Border
borderWidth borderColor
3D Appearance
depth
68
Description Labels that display the numeric value being graphed. By default, value labels are on. You can turn them off or have them display when the user points to the bar (Flash file format only). You can specify the font type (Arial, Courier, or Times), point size, and location (OnBar or OverBar). The minimum and maximum points on the data axis (vertical axis for bar charts, horizontal axis for horizontal bar charts. By default the minimum is 0 and the maximum is the largest data value. The number of grid lines between the top and bottom of the graph. The value of each grid line appears along the value axis. The cfgraph tag displays horizontal grids only. A value of 0 (the default) means no grid lines. Labels to show on the second axis of the chart. Item labels are on by default if you specify an itemColumn (or for cfgraphdata tags, item) attribute. You can specify the label font type (Arial, Courier, or Times), point size, and orientation (horizontal or vertical).
Value axis
scaleFrom scaleTo
Grid lines
gridLines
Item labels
69
Description A comma-separated list of colors to use for each bar. You can use any of the 256 standard Web colors and any valid Web color name notation (for example, blue or ##FF33CC). You must use double pound signs with hexadecimal color notation. These colors replace the standard system-defined colors. If you specify fewer colors than data points, the colors repeat. If you specify more colors than data points, the extra colors are not used. The space, in pixels, between bars. Any 3D shadow specified by the depth attribute appears in this space, so if you want the background to appear between all bars, make the barSpacing value greater than the depth value.
Bar spacing
barSpacing
70
Return to your browser and enter the following URL to view graphdata.cfm: http://127.0.0.1/myapps/graphdata.cfm
Description Put a title above the graph. Give the graph 10 pixels of 3D "depth" shadow. Set the maximum value of the vertical axis to 100000. The minimum value is the default, 0. Make the labels on the horizontal axis 16 points. axis.
itemLabelSize=16
itemLabelOrientation="horizontal" Make the labels horizontal on the horizontal colorList = "red,orange, green,teal,purple" gridLines = 4 barSpacing = 15
Get the bar colors from a custom list. In this example, the graph does not use purple because there are only four data points. Display four grid lines between the top and bottom of the graph. Separate the bars by 15 pixels of background.
71
Description Labels that display the numeric value being graphed. Value labels are on by default. You can turn them off or have them display when the user points to the bar (Flash file format only). You can specify the font type (Arial, Courier, or Times), point size, and location (OnBar or OverBar). A legend relating the pie slice colors to the data point Item descriptions from the itemColumn attribute or cfgraphdata tag itemColumn attribute. By default the legend appears to the left of the chart. You can also specify above, below, right, and none. You can specify the font type as Arial (the default), Courier, or Times. A comma separated list of colors to use for each bar. You can use any of the 256 standard Web colors and any valid Web color name notation (for example, blue or ##FF33CC). You must use double pound signs with hexadecimal color notation. These colors replace the standard system-defined colors. If you specify fewer colors than data points, the colors repeat. If you specify more colors than data points, the extra colors are not used.
Legend
showLegend legendFont
colorList
72
Add the following cfgraph tag before the end of the body:
<!--- Pie graph, from DeptSalaries Query of Queries ---> <cfgraph type="pie" query="DeptSalaries" valueColumn="SumByDept" itemColumn="Dept_Name" title="Total Salaries by Department" titleFont="Times" showValueLabel="rollover" valueLabelFont="Times" borderWidth = 0 backgroundColor = "##CCFFFF" colorlist="##6666FF,##66FF66,##FF6666,##66CCCC" LegendFont="Times"> </cfgraph> <br>
4 5
Save the page. Return to your browser and enter the following URL to view graphdata.cfm: http://127.0.0.1/myapps/graphdata.cfm
73
Description In the DeptSalaries query, add a SUM aggregation function to get the sum of all salaries per department.
<cfset DeptSalaries.SumByDept[i]= In the cfloop, round the salary sums to Round(DeptSalaries.SumByDept[i]/ the nearest thousand. 1000)*1000> <cfgraph type="pie" query="DeptSalaries" valueColumn="SumByDept" itemColumn="Dept_Name"
Create a pie graph using the SumByDept salary sum values from the DeptSalares query. Use the contents of the Dept_Name column for the item labels displayed in the chart legend. Put a title above the graph. Format it in Times font. Display the data value, in Times font, only when the user points to a pie slice. Do not put a border around the chart Set the background for the entire chart area to a light blue. Get the pie slice colors from a custom list, which uses hexadecimal color numbers. The double pound signs prevent ColdFusion from trying to interpret the color data as variable names. Use Times font for the legend.
title="Total Salaries by Department" titleFont="Times" showvalue="rollover" valueLabelFont="Times" borderWidth = 0 backgroundColor = "##CCFFFF" colorList = "##6666FF,##66FF66, ##FF6666,##66AAAA"
LegendFont="Times"
74
Description The minimum and maximum points on the vertical axis. By default the minimum is 0 and the maximum is the largest data value. Labels to show on the horizontal axis of the chart. By default, item labels are on if you specify an itemColumn (or for cfgraphdata tags, item) attribute. You can specify the label font type (Arial, Courier, or Times), point size, and orientation (horizontal or vertical). These attributes specify the line format. For the line color, you can use any of the 256 standard Web colors and any valid Web color name notation (for example, blue or ##FF33CC). You must use double pound signs with hexadecimal color notation. The default line color is blue. You can also specify the line width in pixels. The default is 1 pixel. Specifies whether to fill the area below the line with the line color to form an area graph By default there is no fill. The number of grid lines between the top and bottom of the graph. The value of each grid line appears along the value axis. The cfgraph tag displays horizontal grids only. A value of 0 (the default) means no grid lines.
Item labels
Line characteristics
lineColor lineWidth
Area fill
fill
Grid lines
gridLines
75
Add the following cfgraph tag before the end of the body tag block.
<!--- Area-style Line graph, from HireSalaries Query of Queries ---> <cfgraph type="line" query="HireSalaries" valueColumn="AvgByStart" itemColumn="StartDate" title="Average Salaries by Date of Hire" fileFormat="Flash" GraphWidth=400 BackgroundColor="##FFFF00" Depth=5 lineColor="teal" fill="yes" > </cfgraph> <br>
76
Return to your browser and enter the following URL to view graphdata.cfm: http://127.0.0.1/myapps/graphdata.cfm
Description Add the employee start date to the data in the GetSalaries query.
<cfloop index="i" from="1" Use a cfloop to extract the year of hire to="#GetSalaries.RecordCount#"> from each employees hire data and <cfset GetSalaries.StartDate[i]= convert the result to a four-digit number. NumberFormat(DatePart("yyyy", GetSalaries.StartDate[i]) ,9999)> </cfloop> <cfquery dbtype = "query" name = "HireSalaries"> SELECT StartDate, AVG(Salary) AS AvgByStart FROM GetSalaries GROUP BY StartDate </cfquery>
Create a second query from the GetSalaries query. This query contains the average salary for each start year.
<cfloop index="i" from="1" Round the salaries to the nearest to="#HireSalaries.RecordCount#"> thousand. <cfset HireSalaries.AvgByStart[i] =Round(HireSalaries.AvgByStart[i] /1000)*1000> </cfloop> <cfgraph type="line" query="HireSalaries" valueColumn="AvgByStart" itemColumn="StartDate" title="Average Salaries by Date of Hire" fileFormat="Flash" GraphWidth=400
Create a line graph using the HireSalaries query. Graph the average salaries against the start date. Title the graph. Send the graph to the user as a Flash file. Limit the graph width to 400 pixels. Generator automatically resizes the graphs height to maintain the aspect ratio. Display a 3D graph in teal against a yellow background. Fill the region below the graph to create an area graph.
77
78
ORDER BY Employee.LastName, Employee.Firstname </cfquery> <html> <head> <title>Employee Salary Details</title> </head> <body> <h1><cfoutput>#GetSalaryDetails.Dept_Name[1]# Department Salary Details</cfoutput></h1> <table border cellspacing=0 cellpadding=5> <tr> <th>Employee Name</td> <th>StartDate</td> <th>Salary</td> <th>Contract?</td> </tr> <cfoutput query="GetSalaryDetails" > <tr> <td>#FirstName# #LastName#</td> <td>#dateFormat(StartDate, "mm/dd/yyyy")#</td> <td>#numberFormat(Salary, "$999,999")#</td> <td>#Contract#</td> </tr> </cfoutput> </table> </body> </html>
Save the page as Salary_details.cfm in myapps under the Web root directory.
79
Description Get the salary data for the department whose name was passed in the URL parameter string. Sort the data by the employees last and first names.
Display the data retrieved by the query as a table. Format the start date into standard month/date/year format, and format the salary with a leading dollar sign comma separator, and no decimal places.
80
title="Total Salaries by Department" titleFont="Times" showValueLabel="rollover" valueLabelFont="Times" backgroundColor = "##CCFFFF" borderWidth = 0 colorlist="##6666FF,##66FF66,##FF6666,##66CCCC" LegendFont="Times"> </cfgraph>
3 4
Save the page. Return to your browser and enter the following URL to view graphdata.cfm: http://127.0.0.1/myapps/graphdata.cfm. Click the slices of the pie chart.
Description When the user clicks a data point, call the Salary_Details.cfm page in the current directory, and pass it the parameter named Dept_Name. The parameter value must come from the URLColumn attribute. Complete the URL string with the value from the query Dept_Name field. So, if the Dept_Name is HR, ColdFusion calls the following URL: Salary_Details.cfm?Dept_Name=HR
URLColumn="Dept_Name"
Chapter 6
This chapter explains how to use CFML to dynamically populate forms and dynamically generate SQL. It also discusses ways to make sure that variables exist and have valid data because this information is important to effectively use dynamic data.
Contents
Dynamically Populating List Boxes ......................................................................... 82 Creating Dynamic Check Boxes and Multiple-Selection List Boxes ..................... 84 Ensuring that Variables Exist.................................................................................... 88 Validating Data Types ............................................................................................... 90 Dynamic SQL............................................................................................................. 96
82
83
<!-- radio buttons --> <p> Department:<br> <input type="radio" name="Department" value="Training">Training<br> <input type="radio" name="Department" value="Sales">Sales<br> <input type="radio" name="Department" value="Marketing">Marketing<br> <input type="radio" name="Department" value="HR">HR<br> </p> <!-- check box --> <p> Contractor? <input type="checkbox" name="Contractor" value="Yes" checked>Yes </p> <!-- reset button --> <input type="reset" name="ResetForm" value="Clear Form"> <!-- submit button --> <input type="submit" name="SubmitForm" value="Submit"> </form> </body> </html>
3 4
Save the page as formpage.cfm. View formpage.cfm in a browser. The changes that you just made appear in the form. Remember that you need an action page to submit values.
Description Get the locations of all departments in the Departmt table. The DISTINCT clause eliminates duplicate location names from the returned query results. Populate the City selection list from the Location column of the GetDepartments query. The control has one option for each row returned by the query.
<select name="City"> <cfoutput query="GetDepartments"> <option value="#GetDepartments.Location#"> #GetDepartments.Location# </option> </cfoutput> </select>
84
Note
If the user does not select a check box or make a selection from a list box, no variable is created. The cfinsert and cfupdate tags do not work correctly if there are no values. To correct this problem, make the form fields required, use Dynamic SQL, or use cfparam to establish a default value for the form field. For more information, see the Ensuring that Variables Exist and Dynamic SQL sections later in this chapter.
Check boxes
When you put a series of check boxes with the same name in an HTML form, the variable that is created contains a comma-delimited list of values. The values can be either numeric values or alphanumeric strings. These two types of values are treated slightly differently.
85
The user sees the name of the department, but the value attribute of each check box is a number that corresponds to the underlying database primary key for the departments record. If the user checks the Marketing and Sales items, the value of the SelectedDept form field is "2,4" and you use the SelectedDepts in the following SQL statement:
SELECT * FROM Departmt WHERE Dept_ID IN ( #Form.SelectedDepts# )
If the user checked Marketing and Sales, the value of the SelectedDepts form field would be the list Marketing,Sales.
SELECT * FROM Departmt WHERE Dept_Name IN (#ListQualify(Form.SelectedDepts,"")#)
86
Note
In SQL, all strings must be surrounded in single quotes. The ListQualify function returns a list with the specified qualifying character (here, a single quote) around each item in the list. If you select the second and fourth check boxes in the form, the following statement gets sent to the database:
SELECT * FROM Departmt WHERE Dept_Name IN (Marketing,Sales)
If the user selects the Marketing and Sales items, the value of the SelectDepts form field is 2,4. If this parameter is used in the following SQL statement:
SELECT * FROM Departmt WHERE Dept_ID IN (#form.SelectDepts#)
87
If the user selects the Marketing and Sales items, the SelectDepts form field value is Marketing,Sales. Just as you did when using check boxes to search database fields containing string values, use the ColdFusion ListQualifyfunction with multiple-selection list boxes:
SELECT * FROM Departmt WHERE Dept_Name IN (#ListQualify(Form.SelectDepts,"")#)
88
Note
For information on using the type attribute to validate the parameter data type, see the Using cfparam to validate the data type section of this chapter. There are two ways to use the cfparam tag to test for variable existence, depending on how you want the validation test to proceed: With only the name attribute to test that a required variable exists. If it does not exist, the ColdFusion Server stops processing the page and displays an error message. With the name and default attributes to test for the existence of an optional variable. If the variable exists, processing continues and the value is not changed. If the variable does not exist, it is created and set to the value of the default attribute, and processing continues. The following example shows how to use the cfparam tag to check for the existence of an optional variable and to set a default value if the variable does not already exist:
<cfparam name="Form.Contract" default="Yes">
89
For example, the following series of cfparam tags indicates that this page expects two form variables named StartRow and RowsToFetch:
<cfparam name="Form.StartRow"> <cfparam name="Form.RowsToFetch">
If the page with these tags is called without either one of the form variables, an error occurs and the page stops processing. By default, ColdFusion displays an error message; you can also handle the error as described in Chapter 11, Preventing and Handling Errors on page 191.
You can use cfparam to set default values for URL and Form variables, instead of using conditional logic. For example, the action page could have the following code to ensure that a SelectDepts variable exists:
<cfparam name="Form.SelectedDepts" default="Marketing,Sales">
If the user leaves the FirstName field empty, ColdFusion rejects the form submittal and returns a message informing the user that the field is required. You can customize the contents of this error message using the value attribute of the hidden field. For example, if you want the error message to read You must enter your first name, use the following syntax:
<input type="hidden" name="FirstName_required" value="You must enter your first name.">
90
Note
The data validation discussed in this chapter is done by the ColdFusion Server. Validation using cfform tags is done using JavaScript in the users browser, before any data is sent to the server.
variableName
For example, you can use the following code to validate the variable BirthDate:
<cfparam name="BirthDate" type="date">
91
If the variable is not in a valid date format, an error occurs and the page stops processing.
Value Attribute Custom error message Custom error message MIN=MinValue MAX=MaxValue Custom error message
Description Verifies that the user entered a number. If the user enters a floating point value, it is rounded to an integer. Verifies that the user entered a number. Does not do any rounding of floating point values. Verifies that the numeric value entered is within the specified boundaries. You can specify one or both of the boundaries separated by a space. Verifies that the user entered a date and converts the date into the proper ODBC date format. Will accept most common date forms; for example, 9/1/98; Sept. 9, 1998. Verifies that the user correctly entered a time and converts the time to the proper ODBC time format. Verifies that the user entered a date in a standard European date format and converts into the proper ODBC date format.
_float
_range
_date
_time
_eurodate
Note
Adding a validation rule to a field does not make it a required field. You need to add a separate _required hidden field if you want to ensure user entry. The following procedure creates a simple form for entering a start date and a salary. It uses hidden fields to ensure that you enter data and that the data is in the right format. This example illustrates another concept that might seem surprising. You can use the same CFML page as both a form page and its action page. Because the only action is to display the values of the two variables that you enter, the action is on the same page as the form.
92
Using a single page for both the form and action provides the opportunity to illustrate the use of the IsDefined function to check that data exists. This way, the form does not show any results until you submit the input.
93
3 4
Save the file as datatest.cfm. View the file in your browser, omit a field or enter invalid data, and click the Submit button.
When the user submits the form, ColdFusion scans the form fields to find any validation rules you specified. The rules are then used to analyze the users input. If any of the input rules are violated, ColdFusion sends an error message to the user that explains the problem. The user then must go back to the form, correct the problem. and resubmit the form. ColdFusion does not accept form submission until the user enters the entire form correctly. Because numeric values often contain commas and dollar signs, these characters are automatically deleted from fields with _integer, _float, or _range rules before they are validated and saved to a database.
Description Gather the information from this form using the Post method, and do something with it on the page dataform.cfm, which is this page. Require input into the StartDate input field. If there is no input, display the error information You must enter a start date. Require the input to be in a valid date format. If the input is not valid, display the error information Enter a valid date as the start date. Require input into the Salary input field. If there is no input, display the error information You must enter a salary. Require the input to be in a valid number. If it is not valid, display the error information The salary must be a number. Create a text box called StartDate in which users can enter their starting date. Make it exactly 16 characters wide.
<input type="hidden" name="StartDate_required" value="You must enter a start date."> <input type="hidden" name="StartDate_date" value="Enter a valid date as the start date."> <input type="hidden" name="Salary_required" value="You must enter a salary."> <input type="hidden" name="Salary_float" value="The salary must be a number.">
94
Code
Salary: <input type="text" name="Salary" size="10" maxlength="10"><br> <cfif isdefined("Form.StartDate")> <cfoutput> Start Date is: #DateFormat(Form.StartDate)#<br> Salary is: #DollarFormat(Form.Salary)# </cfoutput> </cfif>
Description Create a text box called Salary in which users can enter their salary. Make it exactly ten characters wide. Output the values of the StartDate and Salary form fields only if they are defined. They are not defined until you submit the form, so they do not appear on the initial form. Use the DateFormat function to display the start date in the default date format. Use the DollarFormat function to display the salary with a dollar sign and commas.
Note
The cfqueryparam tag allows you to specify SQL parameters in queries. It improves performance, maintenance, and security of data queries by improving server-side caching for Oracle databases, supporting updating of long text fields from a SQL statement, and preventing a malicious user from attaching multiple SQL statements to a SQL statement substitution variable. For more information on cfqueryparam and its use, see the CFML Reference. The cfqueryparam tag can have any of several additional advantages, depending on the database system and Web server software that you are using: Some Web servers have security issues in which SQL appended to URL strings can evade system security. cfqueryparam can help prevent this problem. Some database management systems, including some Oracle releases, limit the size of query text fields to 4K bytes. By using cfqueryparam you can overcome this limitation. Using cfqueryparam can speed database processing by using bind parameters.
95
The following example shows the use of cfqueryparam when valid input is given in the Course_ID variable used as a query parameter. To see what happens when you use invalid data, substitute a text string such as test for the integer 12 in the cfset statement. Note that this example uses the cfsnippets database that is provided with ColdFusion, not the CompanyInfo database used in most of this book.
<html> <head> <title>cfqueryparam Example</title> </head> <body> <h3>cfqueryparam Example</h3> <cfset course_id=12> <cfquery name="getFirst" datasource="cfsnippets"> SELECT * FROM courses WHERE Course_ID=<cfqueryparam value="#Course_ID#" cfsqltype="CF_SQL_INTEGER"> </cfquery> <cfoutput query="getFirst"> <p> Course Number: #number#<br> Description: #descript# </p> </cfoutput> </body> </html>
Description Set the course_ID variable to 12. Query the cfsnippets data source and return the results in the getFirst query object. Select all columns from the courses table.
96
Code
WHERE Course_ID=<cfqueryparam value="#Course_ID#" cfsqltype="CF_SQL_INTEGER"> </cfquery>
Description Only select rows where the Course_ID column equals the value of Course_ID CFML local variable. Validate that the variable value is an integer and, if appropriate for the database driver, use a bind parameter to associate the value with the SQL statement. For each row that matches the query, output the contents of the number and descript columns.
<cfoutput query="getFirst"> <p> Department Number: #number#<br> Description: #descript# </p> </cfoutput>
Dynamic SQL
Embedding SQL queries that use dynamic parameters is a powerful mechanism for linking variable inputs to database queries. However, in more sophisticated applications, you often want user inputs to determine not only the content of queries but also the structure of queries. Dynamic SQL allows you to dynamically determine (based on runtime parameters) which parts of a SQL statement are sent to the database. So if a user leaves a search field empty, for example, you can simply omit the part of the WHERE clause that refers to that field. Or, if a user does not specify a sort order, you can omit the entire ORDER BY clause.
The following code creates an application that lets a user search the CompanyInfo database for employees by first name, last name, minimum salary, contract status, or any combination of these criteria.
Dynamic SQL
97
98
Dynamic SQL
99
</body> </html>
3 4 5
Save the page as getemp.cfm. Open the file askemp.cfm in your browser and enter criteria into any fields, then submit the form. Verify that the results meet the criteria you specify.
Description Get the records from the Employee table according to the following conditions. If the user entered anything in the FirstName text box in the form, add "AND Employee.FirstName LIKE [what the user entered in the FirstName text box]%'" to the SQL statement. You can use the FirstName variable without ensuring its existence because text boxes pass an empty string if you do not enter text. If the user entered anything in the LastName text box in the form, add "AND Employee.LastName LIKE [what the user entered in the LastName text box]%'" to the SQL statement. If the user entered anything in the Salary text box in the form, add "AND Employee.Salary >= [what the user entered in the Salary text box]" to the SQL statement.
100
CFML Code
<cfif isDefined("Form.Contract")> Employee.Contract = Yes' AND <cfelse> Employee.Contract = 'No' AND </cfif>
Description If the user selected the Contractor check box, get data for the employees who are contractors; otherwise, get data for employees who are not contractors. The isdefined function test for the existence of the Form.Contract variable is needed because the variable only exists if they select the Contractor box. If none of the conditions are true, the 0=0 statement ensures that the WHERE clause does not result in a SQL syntax error. Instead, the SELECT statement returns the entire table. Putting this statement at the end of the WHERE clause improves security by making it harder to attach extra SQL statements in a dynamic variable, and may affect the databases optimization of the SQL statement.
0=0
Chapter 7
This chapter describes how to insert, update, and delete data in a database with ColdFusion.
Contents
Inserting Data .......................................................................................................... 102 Updating Data ......................................................................................................... 106 Deleting Data........................................................................................................... 112
102
Inserting Data
You usually use two application pages to insert data into a database: An insert form An insert action page You can create an insert form with standard HTML form tags or with cfform tags (see Creating Forms with the cfform Tag on page 136). When the user submits the form, form variables are passed to a ColdFusion action page that performs an insert operation (and whatever else is called for) on the specified data source. The insert action page can contain either a cfinsert tag or a cfquery tag with a SQL INSERT statement. The insert action page should also contain a message for the end user.
Inserting Data
103
3 4
Save the file as insertform.cfm in the myapps directory. View insertform.cfm in a browser.
104
3 4 5
Save the page as insertaction.cfm. View insertform.cfm in a browser, enter values, and click the Submit button. The data is inserted into the Employee table and the message displays.
Description If the user clears the Contractor check box, no value gets passed to the action page. The database field must have a value, so check the Form.contract variable and set it to No if it is not defined. Create a new row in the Employee table of the CompanyInfo database. Insert data from the form into database fields with the same names as the form fields. Inform the user that the data was inserted into the database.
Note
If you use form variables in cfinsert or cfupdate tags, ColdFusion automatically validates any form data it sends to numeric, date, or time data database columns. You can use the hidden field validation functions for these fields to display a custom error message.
Inserting Data
105
4 5 6
Save the page as insertaction.cfm. View insertform.cfm in a browser, enter values, and click Submit. The data is inserted into the Employee table and the message displays.
106
Description Use a cfquery tag to insert a new row into the Employee table of the CompanyInfo Database. Specify each form field to be added. Because the form and database field names are identical, you do not have to specify the database field names in the query.
Updating Data
You usually use two application pages to update data in a database: An update form An update action page You can create an update form with cfform tags or HTML form tags. The update form calls an update action page, which can contain either a cfupdate tag or a cfquery tag with a SQL UPDATE statement. The update action page should also contain a message for the end user that reports on the update completion.
Updating Data
107
3 4
Save the page as updateform.cfm. View updateform.cfm in a browser by specifying the page URL and an Employee ID, for example, http://localhost/myapps/updateform.cfm?Emp_ID=3.
108
Description Query the CompanyInfo data source and return the records in which the employee ID matches what was entered in the URL that called this page. Make the results of the GetRecordtoUpdate query available as variables in the form created on the next line. Create a form whose variables will be processed on the updateaction.cfm action page. Use a hidden input field to pass the employee ID to the action page. Populate the fields of the update form. This example does not use any ColdFusion formatting functions to clean up the form. As a result, the start dates look like 1985-03-12 00:00:00 and the salaries do not have dollar signs or commas. The user can replace the information in any field using any valid input format for the data.
<input type="Hidden" name="Emp_ID" value="#Emp_ID#"><br> First Name: <input type="text" name="FirstName" value="#FirstName#"><br> Last Name: <input type="text" name="LastName" value="#LastName#"><br> Department Number: <input type="text" name="Dept_ID" value="#Dept_ID#"><br> Start Date: <input type="text" name="StartDate" value="#StartDate#"><br> Salary: <input type="text" name="Salary" value="#Salary#"><br>
Contractor: The Contractor field needs special <cfif #Contract# IS "Yes"> treatment because a check box <input type="checkbox" name="Contract" displays and sets its value. Use the checked>Yes<br> cfif structure to put a check mark in <cfelse> <input type="checkbox" name="Contract"> the check box if the Contract field value is Yes, and leave the box Yes <br> </cfif> empty otherwise. <br> <input type="Submit" value="Update Information"> </form> </cfoutput>
Updating Data
109
3 4
Save the page. as updateaction.cfm. View updateform.cfm in a browser by specifying the page URL and an Employee ID, for example, http://localhost/myapps/updateform.cfm?Emp_ID=3. Enter new values in any of the fields, and click the Submit button. The data is updated in the Employee table and the message appears.
110
Description If the user clears the Contractor check box, no value gets passed to the action page. Also, the database field must have a value of Yes or No. Test the Form.contract variable and set it to No if it is not defined and Yes if it is defined. Update the record in the database that matches the primary key on the form (the Emp_ID). Update all fields in the record with names that match the names of controls on the form. Inform the user that the change was made successfully.
<cfoutput> You have updated the information for #Form.FirstName# #Form.LastName# in the Employees database. </cfoutput>
Updating Data
111
<h1>Employee Updated</h1> <cfoutput> You have updated the information for #Form.FirstName# #Form.LastName# in the Employees database. </cfoutput>
3 4
Save the page. View updateform.cfm in a browser by specifying the page URL and an Employee ID, for example, http://localhost/myapps/updateform.cfm?Emp_ID=3. Enter new values in any of the fields, and click Submit. The data is updated into the Employee table and the message displays.
Description Update the record in the database that matches the primary key on the form, (Emp_ID). Update all fields in the record with names that match the names of controls on the form. Because #From.Emp_ID# is numeric, you do not enclose it in quotes.
112
Deleting Data
You use a cfquery tag with a SQL DELETE statement to delete data from a database.
You often want to see the data before you delete it. The following example displays the data to be deleted by reusing the form page used to insert and update data. Any data that you enter in the form before submitting it is not used, so you can use a table to display the record to be deleted instead.
Save the modified file as deleteform.cfm. Create a new application page in ColdFusion Studio. Enter the following code:
<cfquery name="DeleteEmployee" datasource="CompanyInfo"> DELETE FROM Employee WHERE Emp_ID = #Form.Emp_ID# </cfquery> <html> <head> <title>Delete Employee Record</title> </head> <body> <h3>The employee record has been deleted.</h3> <P><cfoutput> You have deleted #Form.FirstName# #Form.LastName# from the Employees database. </cfoutput></P> </body> </html>
Deleting Data
113
View deleteform.cfm a browser by specifying the page URL and an Employee ID, for example, http://localhost/myapps/updateform.cfm?Emp_ID=3. and click the Submit button.
The employee is deleted from the Employee table and the message displays.
Description Delete the record in the database whose Emp_ID column matches the Emp_ID (hidden) field on the form. Since the Emp_ID is the tables primary key, only one record gets deleted. Inform the user that the record was deleted.
To delete all the records from the Employee table, you use the following code:
DELETE FROM Employee
Note
Deleting records from a database is not reversible. Use DELETE statements carefully.
114
Chapter 8
ColdFusion supports dynamic multidimensional arrays. This chapter explains the basics of creating and handling arrays. It also provides several examples showing how arrays can enhance your ColdFusion application code. ColdFusion also supports structures for managing lists of key-value pairs. This chapter explains the basics of creating and working with structures.
Contents
About Arrays ............................................................................................................ 116 Basic Array Techniques........................................................................................... 118 Populating Arrays with Data................................................................................... 121 Array Functions ....................................................................................................... 124 About Structures...................................................................................................... 125 Creating and Using Structures ............................................................................... 127 Structure Functions ................................................................................................ 133
116
About Arrays
Traditionally, an array is a tabular structure used to hold data, much like a spreadsheet table with clearly defined limits and dimensions. A two-dimensional (2D) array is like a simple table. In ColdFusion, you typically use arrays to temporarily store data. For example, if your site allows users to order goods online, you can store their shopping cart contents in an array. This allows you to make changes easily without committing the information, which the user can change before completing the transaction, to a database.
ColdFusion arrays differ somewhat from traditional arrays because they are dynamic. For example, in a conventional array, array size is constant and symmetrical, whereas in a ColdFusion 2D array you can have rows of differing lengths based on the data that has been added or removed. The following figure represents a ColdFusion 2D array:
About Arrays
117
A ColdFusion 2D array is actually a one-dimensional array that contains a series of additional 1D arrays. Each of the arrays that make up a row can expand and contract independently of any other column. The following terms will help you understand subsequent discussions of ColdFusion arrays: Array dimension The relative complexity of the array structure. Index The position of an element in a dimension, ordinarily surrounded by square brackets: my1Darray[1], my2Darray[1][1], my3Darray[1][1][1]. Array element Data stored in an array index. The syntax my2darray[1][3]="Paul" is the same as saying My2dArray is a two-dimensional array and the value of the array element index [1][3] is "Paul". Dynamic arrays expand to accept data you add to them and contract as you remove data from them.
118
At first, the array firstname holds no data and is of an unspecified length. Now you want to add data to the array:
<cfset firstname[1]="Coleman"> <cfset firstname[2]="Charlie"> <cfset firstname[3]="Dexter">
If you remove data from an array, the array resizes dynamically. Use the ArrayDeleteAt function to delete data from the array at a particular index, rather than set the data value to 0 or the empty string:
<cfset temp=ArrayDeleteAt(firstname, 2)> <!--- "Charlie" has been removed from the array ---> <cfoutput> The firstname array is #ArrayLen(firstname)# indexes in length </cfoutput> <!--- Now the array has a length of 2, not 3 --->
Creating an array
In ColdFusion, you declare an array by assigning a variable name to the new array as follows:
<cfset mynewarray=ArrayNew(x)>
where x is the number of dimensions (from 1 to 3) in the array that you want to create. Once created, you can add data to the array, in this case using a form variable:
<cfset mynewarray[4]=Form.emailaddress>
119
But you can also use a number of array functions to add data to an array. You can use the following functions: Function
ArrayAppend ArrayPrepend ArrayInsertAt
Description Creates a new array index at the end of the array Creates a new array index at the beginning of the array Inserts an array index and data
When you insert an array index with ArrayInsertAt, all indexes to the right of the new index are recalculated to reflect the new index count. For more information about these array functions, see the CFML Reference.
Note
Because ColdFusion arrays are dynamic, if you add or delete an element from the middle of an array, higher-numbered index values all change.
120
<!--- This example adds a 1D array to a 1D array ---> <!--- Declare two one-dimensional arrays for the first and last names ---> <cfset firstname=arraynew(1)> <cfset lastname=arraynew(1)> <!--- Assign first names directly to the firstname array ---> <cfset firstname[1]="Coleman"> <cfset firstname[2]="Charlie"> <cfset firstname[3]="Dexter"> <!--- Declare the full name array ---> <cfset fullname=arraynew(1)> <!--- Add the firstname array to index 1 and the lastname array to index 2 of the fullname array ---> <cfset fullname[1]=firstname> <cfset fullname[2]=Lastname> <!--- Add the last names using reference to the fullname array ---> <cfset fullname[2][1]="Hawkins"> <cfset fullname[2][2]="Parker"> <cfset fullname[2][3]="Gordon"> <cfoutput> #fullname[1][1]# #fullname[1][2]# #fullname[1][3]# #fullname[1][1]# </cfoutput>
Note that because this is a full 2D array, you can easily output names that do not make sense in the real world.
121
This example initializes the array myarray, indexes 1 to 100, with an empty string.
ArraySet (myarray, 1, 100, "")
122
123
In the following example, a cfloop places four columns of data from a sample data source into an array, "myarray."
<!--- Do the query ---> <cfquery name="test" datasource="cfsnippets"> SELECT Emp_ID, LastName, FirstName, Email FROM Employees </cfquery> <!--- Declare the array ---> <cfset myarray=arraynew(2)> <!--- Populate the array row by row ---> <cfloop query="test"> <cfset myarray[currentrow][1]=Emp_ID[currentrow]> <cfset myarray[currentrow][2]=LastName[currentrow]> <cfset myarray[currentrow][3]=FirstName[currentrow]> <cfset myarray[currentrow][4]=Email[currentrow]> </cfloop> <!--- Now, create a loop to output the array contents ---> <cfset total_records=test.recordcount> <cfloop index="Counter" from=1 to="#Total_Records#"> <cfoutput> ID: #MyArray[Counter][1]#, LASTNAME: #MyArray[Counter][2]#, FIRSTNAME: #MyArray[Counter][3]#, EMAIL: #MyArray[Counter][4]# <br> </cfoutput> </cfloop>
124
Array Functions
The following functions are available for creating, editing, and handling arrays: Function
ArrayAppend ArrayAvg ArrayClear ArrayDeleteAt
Description Appends an array element to the end of a specified array. Returns the average of the values in the specified array. Deletes all data in a specified array. Deletes an element from a specified array at the specified index and resizes the array. Inserts an element (with data) in a specified array at the specified index and resizes the array. Returns True if the specified array is empty of data. Returns the length of the specified array. Returns the largest numeric value in the specified array. Returns the smallest numeric value in the specified array. Creates a new array of specified dimension. Adds an array element to the beginning of the specified array. Resets an array to a specified minimum number of elements. Sets the elements in a 1D array in a specified range to a specified value. Returns the specified array with elements sorted numerically or alphanumerically. Returns the sum of values in the specified array. Swaps array values in the specified indexes. Converts the specified one dimensional array to a list, delimited with the character you specify. Returns True if the value is an array. Converts the specified list, delimited with the character you specify, to an array.
ArrayInsertAt
ArraySort
IsArray ListToArray
For more information about each of these functions, see the CFML Reference.
About Structures
125
About Structures
ColdFusion structures consist of key-value pairs. Structures let you build a collection of related variables that are grouped under a single name. You can define ColdFusion structures dynamically. You can use structures to refer to related values as a unit rather than individually. To maintain employee lists, for example, you can create a structure that holds personnel information such as name, address, phone number, ID numbers, and so on. Then you can refer to this collection of information as a structure called employee rather than as a collection of individual variables. A structures key must be a string. The values associated with the key can be anything; for example, a string, an integer, an array, or another structure. Because structures can contain both structures and arrays, they provide a very powerful and flexible mechanism for representing complex data. You can use structures as associative arrays. When used as associative arrays, structures index repetitive data by string keys rather than by integers. For example, you might use structures to create an associative array that matches peoples names with their departments. In this example, a structure named Departments includes an employee named John, listed in the Sales department. To access Johns department, you would use the syntax, Departments["John"].
126
Structure notation
ColdFusion supports three types of notation for structures. Which notation you use depends on your needs: Notation Object.property Description Use to refer to values in a structure. You can refer to a property, prop, of an object, obj, as obj.prop. This notation is useful for simple assignments, as in this example:
depts.John="Sales"
Use this notation only when you know the property names (keys) in advance and they are strings, with no special characters, numbers, or spaces. You cannot use the dot notation when the property, or key, is dynamic. Associative arrays If you do not know the key name is in advance, or it contains spaces, numbers or special characters, you can use associative array notation. This notation uses structures as arrays with string indexes, for example, depts["John"] or depts["John Doe"]="Sales.". Use structure functions when you cannot use the simpler syntax styles. You must use structure functions to create and remove structures and their elements, including renaming keys. You do not need structure functions to access value data in structures or to change the values in the key value pairs.
Structure functions
127
Creating structures
You create structures by assigning a variable name to the structure with the StructNew function:
<cfset mystructure=StructNew()>
Now the structure exists and you can add data to it.
The AllowOverwrite parameter is optional and can be either True or False. You can use it to specify whether an existing key should be overwritten. The default is False. When adding string values to a structure, enclose the string in quotation marks. For example, to add a key, John, with a value, Sales, to an existing structure called Departments, use this syntax:
<cfset value=StructInsert(Departments, "John", "Sales")>
The following example shows how to add content to a sample structure named employee, building the content of the value fields dynamically using form variables:
<cfset <cfset <cfset <cfset <cfset rc=StructInsert(employee, rc=StructInsert(employee, rc=StructInsert(employee, rc=StructInsert(employee, rc=StructInsert(employee, "firstname", "#FORM.firstname#")> "lastname", "#FORM.lastname#")> "email", "#FORM.email#")> "phone", "#FORM.phone#")> "department", "#FORM.department#")>
128
For more information on using cfscript, see Chapter 13, Extending ColdFusion Pages with CFML Scripting on page 243
129
This function returns True if variable is a structure. Structures are not indexed numerically, so to find out how many name-value pairs exist in a structure, use the StructCount function, as in this example:
StructCount(employee)
To discover whether a specific Structure contains data, use the StructIsEmpty function:
StructIsEmpty(structure_name)
This function returns True if the structure is empty and False if it contains data.
If the name of the key is known in advance, you can use the ColdFusion function IsDefined, as in this example:
<cfset temp=IsDefined("structure_name.key")>
But if the key is dynamic, or contains special characters, you must use the StructKeyExists function:
<cfset temp=StructKeyExists(structure_name, key)>
You can also use the StructFind function to find a key and return its value, as in this example:
<cfset keyvalue=StructFind(structure_name, key)>
The delimiter can be any delimiter, but the default is a comma ( , ). The StructKeyArray function returns an array of keys in a structure:
<cfset temp=StructKeyArray(structure_name)>
Note
The StructKeyList and StructKeyArray functions do not return keys in any particular order. Use the ListSort or ArraySort function to sort the results.
130
Copying structures
To copy a structure, use the StructCopy function. This function takes the name of the structure that you want to copy and returns a new structure with all the keys and values of the named structure.
StructCopy(structure)
This function throws an exception if structure does not exist. Use the StructCopy function when you want to create a physical copy of a structure. You can also use assignment to create a copy by reference.
Deleting structures
To delete an individual name-value pair in a structure, use the StructDelete function:
StructDelete(structure_name, key [, indicatenotexisting ])
This deletes the named key and its associated value. Note that the indicatenotexisting parameter indicates whether the function returns False if the named key does not exist. The default is False, which means that the function returns Yes regardless of whether key exists. If you specify True for this parameter, the function returns Yes if key exists and No if it does not. You can also use the StructClear function to delete all the data in a structure but keep the structure instance itself:
StructClear(structure_name)
Structure example
Structures are particularly useful for grouping together a set of variables under a single name. In the following example, structures are used to collect information from a form, structinsert.cfm, and to submit that information to a custom tag at addemployee.cfm. This examples show how you can use a structure to pass information to a custom tag, named cf_addemployee. For information on creating and using custom tags, see Reusing Code on page 171.
131
<body> <h1>Add New Employees</h1> <!--- Action page code for the form at the bottom of this page ---> <!--- Establish parameters for first time through ---> <cfparam name="Form.firstname" default=""> <cfparam name="Form.lastname" default=""> <cfparam name="Form.email" default=""> <cfparam name="Form.phone" default=""> <cfparam name="Form.department" default=""> <!--- If at least the firstaname form field is passed, create a structure named employee and add values ---> <cfif #form.firstname# eq ""> <p>Please fill out the form. <cfelse> <cfoutput> <cfscript> employee=StructNew(); StructInsert(employee, "firstname", "#FORM.firstname#"); StructInsert(employee, "lastname", "#FORM.lastname#"); StructInsert(employee, "email", "#FORM.email#"); StructInsert(employee, "phone", "#FORM.phone#"); StructInsert(employee, "department", "#FORM.department#"); </cfscript> <!--- Display results of creating the structure ---> <p>First name is #StructFind(employee, "firstname")#</p> <p>Last name is #StructFind(employee, "lastname")#</p> <p>EMail is #StructFind(employee, "email")#</p> <p>Phone is #StructFind(employee, "phone")#</p> <p>Department is #StructFind(employee, "department")#</p> </cfoutput> <!--- Call the custom tag that adds employees ---> <cf_addemployee empinfo="#employee#"> </cfif> <!--- The form for adding the new employee information ---> <hr> <form action="structinsert.cfm" method="Post"> <p>First Name: <input name="firstname" type="text" hspace="30" maxlength="30"> <p>Last Name: <input name="lastname" type="text" hspace="30" maxlength="30"> <p>EMail: <input name="email" type="text" hspace="30" maxlength="30"> <p>Phone: <input name="phone" type="text" hspace="20" maxlength="20"> <p>Department: <input name="department" type="text" hspace="30" maxlength="30"> <p>
132
Structure Functions
133
<table cellpadding="2" cellspacing="2"> <tr> <td><b>Employee</b></td> <td><b>Department</b></td> </tr> <!--- In cfloop, use item to create a variable called person to hold value of key as loop runs ---> <cfloop collection=#departments# item="person"> <tr> <td>#person#</td> <td>#Departments[person]#</td> </tr> </cfloop> </table> </cfoutput>
Structure Functions
Use the following functions to create and manage structures in ColdFusion applications: Function
IsStruct StructClear StructCopy
Description Returns True if the specified variable is a structure. Removes all data from the specified structure. Returns a new structure with all the keys and values of the specified structure. Returns the number of keys in the specified structure. Removes the specified item from the specified structure. Returns the value associated with the specified key in the specified structure. Inserts the specified key-value pair into the specified structure. Indicates whether the specified structure contains data. Returns True if the structure contains no data, and False if it does contain data. Returns an array of keys in the specified structure. Returns True if the specified key is in the specified structure. Returns a list of keys in the specified structure. Returns a new structure. Updates the specified key with the specified value.
StructInsert
StructIsEmpty
134
Note that in all cases, except StructDelete, an exception is thrown if the referenced key or structure does not exist. For more information on these functions, see the CFML Reference.
Chapter 9
This chapter shows you how to use the cfform tag to enrich your forms with sophisticated graphical controls, including several Java applet-based controls. You can use these controls without writing a line of Java code.
Contents
Creating Forms with the cfform Tag ...................................................................... 136 Input Validation with cfform Controls .................................................................. 139 Input Validation with JavaScript ............................................................................ 144 Building Tree Controls with cftree ......................................................................... 147 Structuring Tree Controls ....................................................................................... 150 Embedding URLs in a cftree................................................................................... 152 Creating Data Grids with cfgrid ............................................................................. 153 Creating an Updateable Grid ................................................................................. 155 Building Slider Bar Controls ................................................................................... 164 Building Text Entry Boxes ....................................................................................... 165 Building Drop-Down List Boxes............................................................................. 166 Embedding Java Applets ......................................................................................... 167
136
137
cfform controls
The following table describes the controls ColdFusion controls you use in forms created using cfform: Control
cfgrid
Description A Java applet-based control that creates a data grid you can populate from a query or by defining the contents of individual cells. You can also use grids to insert, update, and delete records from a data source. A Java applet-based control that defines a slider. Places radio buttons, check boxes, text input boxes, and password entry boxes in your form (not a Java applet). Java applet-based controls that define a tree control and individual tree control items. A Java applet-based control that defines a text input box. Defines a drop-down list box not a Java applet). Embed your own Java applets in the form.
138
Usage notes
In cftree, the preservedata attribute causes the tree to expand the tree to the previously selected element. For this to work correctly, you must also set the completePath attribute to True. The preservedata attribute has no effect on cfgrid. If you populate the control from a query, you should update the data source with the new data (typically by using cfgridupdate) before redisplaying the grid. The grid then displays the updated database information.
Browser considerations
The applet-based controls for cfformcfgrid, cfslider, cftextinput, and cftreeuse JavaScript and Java to display their content. To allow them to display consistently across a variety of browsers, these applets use the Java plug-in, and not the browsers native Java runtime. As a result, they are independent of the level of Java support provided by the browser. ColdFusion downloads and installs the browser plug-in if necessary. Some browsers display a single permission dialog box asking you to confirm the plug-in install. Other browsers, particularly older versions of Netscape, require you to navigate some simple option screens. Because the controls use JavaScript to return data to ColdFusion, if you disable JavaScript in your browser it cannot properly run forms that contain these controls. In that case, the controls still display, but data return and validation does not work and you may receive a JavaScript error. Because Java is handled by the plug-in and not directly by the browser, disabling Java execution in the browser should not affect the operation of the controls. If for some other reason, however, the browser is unable to render the controls as requested, a "notsupported" message displays in place of the control. You can use the cfform tags notsupported attribute to specify an alternate error message.
139
Zipcode
When you specify an input type in the validate attribute, ColdFusion tests for the specified input type when you submit the form, and submits form data only on a successful match. A successful form submission returns the value True and returns the value False if validation fails.
140
Special characters
Because special characters are the operators in regular expressions, in order to represent a special character as an ordinary one, you need to precede it with a backslash. For example, use a double backslash (\\) to represent a backslash.
141
If the first character of a set of characters in bracket is the caret (^), the expression matches any character except those in the set. It does not match the empty string. For example: [^akm] matches any character except "a", "k", or "m". The caret loses its special meaning if it is not the first character of the set. You can make regular expressions case insensitive by substituting individual characters with character sets, for example, [Nn][Ii][Cc][Kk]. You can use the following escape sequences to match specific characters or character classes: Escape Matches Seq
[\b] Backspace
\b \B \cX
A word boundary such as a space A non-word boundary The control character Ctrl-x. For example, \cv matches Ctrl-v, the usual control character for pasting text. A digit character [0-9]
\S \t \v
\d
\w
An alphanumeric character or underscore. The equivalent of [A-Za-z0-9_] Any character not matched by \w. The equivalent of [^A-Za-z0-9_] a backreference to the nth expression in parentheses. See Backreferences The character represented in the ASII character table by the specified octal number The character represented in the ASCII character table by the specified hexadecimal number
\D \f
\W \n
\n
Line feed
\ooctal
\r
Carriage return
\xhex
142
A one-character regular expression or grouped subexpression followed by a plus (+) matches one or more occurrences of the regular expression. For example, [a-z]+ matches one or more lowercase characters. A one-character regular expression or grouped subexpression followed by a question mark (?) matches zero or one occurrences of the regular expression. For example, xy?z matches either "xyz" or "xz". The carat (^) at the beginning of a regular expression matches the beginning of the field. The dollar sign ($) at the end of a regular expression matches the end of the field. The concatenation of regular expressions creates a regular expression that matches the corresponding concatenation of strings. For example, [A-Z][a-z]* matches any capitalized word. The OR character (|) allows a choice between two regular expressions. For example, jell(y|ies) matches either "jelly" or "jellies". Braces ({}) are used to indicate a range of occurrences of a regular expression, in the form {m, n} where m is a positive integer equal to or greater than zero indicating the start of the range and n is equal to or greater than m, indicating the end of the range. For example, (ba){0,3} matches up to three pairs of the expression "ba". The form {m,} requires at least m occurrences of the preceding regular expression. The form {m} requires exactly m occurrences of the preceding regular expression.The syntax {,n} is not allowed.
Backreferences
Backreferencing allows you to match text in previously matched sets of parentheses. A slash followed by a digit n (\n) refers to the nth parenthesized subexpression. One example of how you can use backreferencing is searching for doubled words; for example, to find instances of the the or is is in text. The following example shows the syntax you use for backreferencing in regular expressions:
(\b[A-Za-z]+)[ ]+\1
This code matches text that contains a word (specified by the \b word boundary special character and the [A-Za-z]+) followed by one or more spaces [ ]+, followed by the first matched subexpression in parentheses. For example, it would match is is, or This is is, but not This is.
143
Expression examples
The following examples show some regular expressions and describe what they match: Expression
[\?&]value= ^[A-Z]:(\\[A-Z0-9_]+)+$
Description Any string containing a URL parameter value. An uppercase DOS/Windows directory path that is not the root of a drive and has only letters, numbers, and underscores in its text. An integer that does not begin with a zero and has an optional sign. A real number. A string containing two to four occurrences of a: aa, aaa, aaaa; for example aardvark, but not automatic. A string containing least two ba pairs; for example Ali baba, but not Ali Baba.
^(\+|-)?[1-9][0-9]*$ ^(\+|-)?[1-9][0-9]*(\.[0-9]*)?$
(ba){2,}
Resources
An excellent reference on regular expressions is Mastering Regular Expressions by Jeffrey E.F. Friedl, published by OReilly & Associates, Inc.
144
145
3 4
146
Description JavaScript code to test for valid entry in the text box. The if statement checks to making sure that the field is not empty and contains an at sign (@) that at least the second character and a period (.) that is at least the fourth character.
Calls the JavaScript testbox function to validate entries in this control. Message to display if the validation function returns a false value.
See the following Web site for information on JavaScript validation scripts: http:// www.dannyg.com/javascript.
147
Description Create a tree and name it tree1. Specify that a user must select an item in the tree. Dont allow horizontal scrolling.
<cftreeitem value=FullName Create an item in the tree and put the results of the query="engquery" query named engquery in it. Because this tag uses
Specify the query name as the root level of the tree control. Use the images "folder" and "document" that ship with ColdFusion in the tree structure.
148
149
<cftreeitem value="Dept_ID, Populate the tree with the Department ID, and under FullName" each department, the Full Name for each employee
in the department.
queryasroot="Dept_ID" img="cd,folder">
Label the root "Dept_ID". Use the ColdFusion-supplied CD image for the root level and Folder image for the department IDs. The names are preceded by a bullet.
Note that the cftreeitem comma-separated img and the value attributes both correspond to the tree level structure. If you leave out the img attribute, ColdFusion uses the folder image for all levels in the tree except the individual items, which have bullets.
You can specify the character used to delimit each element of the path form variable in the cftree delimiter attribute. The default is a backslash.
Input validation
Although, the cftree does not include a validate attribute, you can use the required attribute to force a user to select an item from the tree control. In addition, you can use the onvalidate attribute to specify the JavaScript code to perform validation.
150
151
parent="Divisions" img="folder"> <cftreeitem value="Product One" parent="QA"> <cftreeitem value="Product Two" parent="QA"> <cftreeitem value="Product Three" parent="QA"> <cftreeitem value="Support" parent="Divisions" img="fixed"> <cftreeitem value="Product Two" parent="Support"> <cftreeitem value="Sales" parent="Divisions" img="cd"> <cftreeitem value="Marketing" parent="Divisions" img="document"> <cftreeitem value="Finance" parent="Divisions" img="element"> </cftree> </cfform>
152
Description Make the node of the tree a link. Make the node of the tree a link. Note that, although this example does not show it, href can refer to the name of a column in a query if the tree item is populated from that query.
153
Automatically passing the name of the selected tree item as part of the URL makes it easy to implement a basic "drill down" application that displays additional information based on the selection. For example, if the specified URL is another CFML page, it can access the selected value as the variable URL.cfteeitemkey. You can disable this behavior by setting the appendkey attribute in the cftree tag to No.
154
Note Use the cfgridcolumn display="No" attribute to hide columns you want to include in the grid but not expose to an end user. You would typically use this attribute to include columns such as the tables primary key column in the results returned by cfgrid without exposing this data to the user. 3 Save the file and view it in your browser.
Description Create a grid named "employee_grid" and populate it with the results of the query "empdata". Allow the user to select only one cell. Other modes are row, column and edit. Put the contents of the Emp_ID column in the query results in the first column of the grid. Put the contents of the LastName column in the query results in the second column of the grid. query results in the third column of the grid.
155
Note If you specify a cfgrid tag with a query attribute defined and no corresponding cfgriditem attributes the grid contains all the columns in the query.
156
Description Stores the original value of the edited grid cell. Stores the edit type made to the edited grid row: D for delete, I for insert, or U for update.
When a user selects and changes data in a row, ColdFusion creates arrays to store the following information for rows that are updated, inserted, or deleted: The original values for all columns The new column values The type of change For example, the following arrays are created if you an update a cfgrid called "mygrid" consisting of two displayable columns, (col1, col2) and one hidden column (col3).
Form.mygrid.col1[ change_index ] Form.mygrid.col2[ change_index ] Form.mygrid.col3[ change_index ] Form.mygrid.original.col1[ change_index ] Form.mygrid.original.col2[ change_index ] Form.mygrid.original.col3[ change_index ] Form.mygrid.RowStatus.Action[ change_index ]
157
The value of change_index increments for each row that changes, and does not indicate the specific row number. When the user updates data or inserts or deletes rows, the action page gets one array for each changed column, plus the RowStatsus.Action array. The action page does not get arrays for unchanged columns. If the user makes a change to a single cell in col2, you can access the edit operation, the original cell value, and the edited cell value in the following arrays:
Form.mygrid.RowStatus.Action[1] Form.mygrid.col2[1]> Form.mygrid.original.col2[1]>
If the user changes the values of the cells in col1 and col3 in one row and the cell in col2 in another row, the information about the original and changed values is in the following array entries:
Form.mygrid.RowStatus.Action[1]><BR> Form.mygrid.col1[1]><BR> Form.mygrid.original.col1[1]> Form.mygrid.col3[1]><BR> Form.mygrid.original.col3[1]> Form.mygrid.RowStatus.Action[2]><BR> Form.mygrid.col2[2]><BR> Form.mygrid.original.col2[2]>
158
159
Description Populate a cfgrid control with data from the empdata query. Selecting a grid cell enables you to edit it. Rows can be inserted and deleted. The grid is 300 X 250 pixels and has 10 pixels of space above and below it.
Create a 50-pixel wide column for the data in the Emp_ID column of the data source. Center a header named Emp ID and make it bold. Do not allow users to select fields in this column for editing. Since this field is the tables primary key, users should not be able to change it for existing records and the DBMS should generate this field as an automincrement value.
<cfgridcolumn name="LastName" Create a 100-pixel wide column for the data in header="Last Name" the LastName column of the data source. Center width=100 a header named Last Name and make it bold. headeralign="center" headerbold="Yes"> <cfgridcolumn name="Dept_ID" header="Dept" width=35 headeralign="center" headerbold="Yes">
Create a 35-pixel wide column for the data in the Dept_ID column of the data source. Center a header named Dept and make it bold.
160
3 4
Save the file as handle_grid.cfm. View grid2.cfm in your browser, make changes to the grid, and then submit them.
161
<br> </cfoutput> <cfif Form.employee_grid.rowstatus.action[counter] is "D"> <cfquery name="DeleteExistingEmployee" datasource="CompanyInfo"> DELETE FROM Employee WHERE Emp_ID=#Form.employee_grid.original.Emp_ID [Counter]# </cfquery> <cfelseif Form.employee_grid.rowstatus.action[counter] is "U"> <cfquery name="UpdateExistingEmployee" datasource="CompanyInfo"> UPDATE Employee SET LastName=#Form.employee_grid.LastName[Counter]#, Dept_ID=#Form.employee_grid.Dept_ID[Counter]# WHERE Emp_ID=#Form.employee_grid.original.Emp_ID [Counter]# </cfquery> <cfelseif Form.employee_grid.rowstatus.action[counter] is "I"> <cfquery name="InsertNewEmployee" datasource="CompanyInfo"> INSERT into Employee (LastName, Dept_ID) VALUES (#Form.employee_grid.LastName[Counter]#, #Form.employee_grid.Dept_ID[Counter]#) </cfquery> </cfif> </cfloop> </cfif> </body> </html>
3 4
Rename your existing handle_grid.cfm file if you wish to save it, then save this file as handle_grid.cfm. View grid2.cfm in your browser, make changes to the grid, and then submit them.
162
Description If there is an array of edit types, then the table needs changing. Otherwise, do nothing. Loop through the remaining code once for each row to be changed. Counter is the common index into the arrays of change information for the row being changed. Display the action code for this row: U, I, or D.
<cfoutput> The row action for #Counter# is: #Form.employee_grid.rowstatus.action[Counter]# <br> </cfoutput> <cfif Form.employee_grid.rowstatus.action[counter] is "D"> <cfquery name="DeleteExistingEmployee" datasource="CompanyInfo"> DELETE FROM Employee WHERE Emp_ID=#Form.employee_grid.original .Emp_ID[Counter]# </cfquery> <cfelseif Form.employee_grid.rowstatus.action [counter] is "U"> <cfquery name="UpdateExistingEmployee" datasource="CompanyInfo"> UPDATE Employee SET LastName= #Form.employee_grid.LastName[Counter]#, Dept_ID= #Form.employee_grid.Dept_ID[Counter]# WHERE Emp_ID=#Form.employee_grid.original. Emp_ID[Counter]# </cfquery>
If the action is to delete a row, generate a SQL DELETE query specifying the Emp_ID (the primary key) of the row to be deleted.
Otherwise, if the action is to update a row, generate a SQL UPDATE query to update the LastName and Dept_ID fields for the row specified by the Emp_ID primary table key.
163
Code
<cfelseif Form.employee_grid.rowstatus.action[counter] is "I"> <cfquery name="InsertNewEmployee" datasource="CompanyInfo"> INSERT into Employee (LastName, Dept_ID) VALUES (#Form.employee_grid.LastName[Counter]#, #Form.employee_grid.Dept_ID[Counter]#) </cfquery> </cfif> </cfloop> </cfif>
Description Otherwise, if the action is to insert a row, generate a SQL INSERT query to insert the Employees last name and department ID from the grid row into the database. The Insert operation assumes that the DBMS automatically increments the Emp_ID primary key. If you use the Dbase version of the CompanyInfo database that is provided for UNIX installations, the record is inserted without an Emp_ID number.
Close the cfif tag used to select among deleting, updating, and inserting. Close the loop used for each row to be changed. Close the cfif tag that surrounds all the active code.
164
To get the value of the slider in the action page, use the variable Form.slider_name; in this case, Form.myslider.
165
To get the value of the input text in the action page, use the variable Form.textinput_name; in this case, Form.entertext.
166
Note that because the tag includes the multiple attribute, the user can select multiple entries in the list box. Also, because the value tag specifies Emp_ID, the primary key for the Employee table, Employee IDs (not first names) get passed in the Form.Employee variable to the application page specified in the cfform action attribute.
167
By contrast, with the HTML applet tag, you must declare all the applets parameters every time you want to use it in a ColdFusion page.
2 3 4
168
Code
Method
Java Not Supported Message This message is displayed by browsers that do not support Java applets. If you want to override this message, you specify a different message in the cfapplet notsupported attribute. Parameter Name Enter a name for a required applet parameter. Your Java applet typically provides the parameter name needed to use the applet. Enter each parameter in a separate parameter field. For every parameter you enter, define a default value. Your applet documentation provides guidelines on valid entries.
Value
169
170
When your page executes the applet, a form variable is created with the name that you specified. If you do not specify a method, no form variable is created.
Chapter 10
Reusing Code
This chapter describes how to reuse common code with cfinclude, and create custom CFML tags that encapsulate common code.
Contents
Ways to Reuse Code ................................................................................................ 172 Reusing Common Code with cfinclude................................................................. 172 Using Custom Tags.................................................................................................. 173 Nesting Custom Tags............................................................................................... 180 Passing Data Between Nested Custom Tags.......................................................... 181 Executing Custom Tags........................................................................................... 185 Installing Custom Tags............................................................................................ 187 Managing Custom Tags........................................................................................... 188
172
(Of course, for this code to work you must also put your companys logo as a gif file in the same directory as header.cfm.) 2 3 Open the file askemp.cfm in ColdFusion Studio. Include header.cfm in this page by adding the following line just below the <body> tag:
<cfinclude template="header.cfm">
4 5
173
6 7
View askemp.cfm in a browser, then submit the form so that you display getemp.cfm. The header should appear on both pages.
Note The file header.cfm must be in the same directory where you saved askemp.cfm and getemp.cfm (or a subdirectory). If it is not, make sure it is in a directory that has a mapping defined in ColdFusion Administrator, or move it to the appropriate directory.
A custom tag can also have a body and end tag, for example:
<CF_HappyBirthdayMessge name="Ellen Janes" birthDate="June, 8, 1993"> <P> Happy Birthday Ellen!</P> <P> May you have many more!</P> </CF_HappyBirthdayMessage>
You call custom tags by adding the cf_ prefix to the filename (without the .cfm suffix). For example, use the tag name cf_getweather to call the file getweather.cfm. You must store custom tags that you call directly in either the same directory as the calling page, in the CFUSION\CustomTags directory, or in a subdirectory of the CFUSION\CustomTags directory. Each file defines a single custom tag. You can also use the cfmodule tag to call custom tags. The cfmodule tag lets you specify the location of the custom tag file. The cfmodule tag is useful if you are concerned about possible name conflicts when invoking a custom tag or if the application must use a variable to dynamically call a custom tag at runtime. For more information on using the cfmodule tag, see theCFML Reference.
174
In this case, the mytag.cfm custom tag page refers to the passed attributes as Attributes.Firstname and Attributes.Lastname. Use the Caller scope in the custom tag page to refer to local variables in the calling tag page. You use the Caller scope to return values to the calling page, but you can also use this scope to access any local variables on the calling page. Use the Request scope for variables in nested tags. The Request scope is available to the base page, all pages it includes, all custom tag pages it calls, and all custom tag pages called by the included pages and custom tag pages. Collaborating custom tags that are not nested in a single tag can exchange data via the request structure. The Request scope is represented as a structure named Request.
175
Custom tag pages also have access to system data structure called thisTag. The thisTag structure contains information about the tag and its execution environment. The thisTag variable is described in Executing Custom Tags, on page 185.
176
In the getmd.cfm file, you refer to the passed attribute as Attributes.Name. To pass values back to the calling page, use the Caller scope. The custom tag page can also access variables already set on the calling by simply prefixing the calling pages local variable name with Caller. For example, use the following code to set the variable Doctor on the calling page:
<cfset Caller.Doctor="Doctor " & Attributes.Name>
The following figure shows the relation between the variables on the calling page and the custom tag:
177
178
3 4 5
Save the page as callingpage.cfm. Create another new page (the custom tag) in ColdFusion Studio. Enter the following code:
<!--- The value of the variable Attributes.Name comes from the calling page. If the calling page does not set it, make it Who. ---> <cfparam name="Attributes.Name" default="Who"> <!--- Create a variable called followed by the value of Make its scope Caller so ---> <cfset Caller.Doctor="Doctor " Doctor, make its value "Doctor " the variable Attributes.Name. it is passed back to the calling page & Attributes.Name>
6 7
Save the page as getmd.cfm. Open the file callingpage.cfm in your browser.
The calling page uses the getmd custom tag and displays the results.
179
Description In the calling page, create a variable NameYouEntered and assign it the value "Smith." In the calling page, display the value of the NameYouEntered variable before calling the custom tag.
<cfoutput> Before you leave this page, youre #NameYouEntered#.<br> </cfoutput> <CF_GetMD Name="#NameYouEntered#">
In the calling page, call the GetMD custom tag and pass it the Name attribute whose value is the value of the local variable NameYouEntered. The custom tag page normally gets the Name variable in the Attributes scope from the calling page. Assign it the value "Who" if the calling page did not pass an attribute. In the custom tag page, create a variable called Doctor in the Caller scope so it will exist in the calling page as a local variable. Set its value to the concatenation of the string Doctor and the value of the Atributes.Name variable. In the calling page, display the value of the Doctor variable returned by the custom tag page. (We use the Variables scope prefix to emphasize the fact that the variable is returned as a local variable.)
Tip Be careful not to overwrite variables that might already exist on the calling page. You should adopt a naming convention to minimize the chance of overwriting variables. For example, prefix the returned variable with customtagname_, with customtagname being the name of the custom tag. Note Data pertaining to the HTTP request or to the current application is visible in the custom tag page. This includes the variables in the Form, Url, Cgi, Request, Cookies, Server, Application, Session, and Client scopes.
180
In order to nest tags, the parent tag must have a closing tag. You can create multiple levels of nested tags. In this case, the sub tag becomes the base tag for its own sub tags. Any tag with an end tag present can be an ancestor to another tag. Nested custom tags operate through three modes of processing, which are exposed to the base tags through the variable thisTag.ExecutionMode: The start mode, in which the base tag is processed for the first time. The inactive mode, in which sub tags and other code contained within the base tag are processed. No processing occurs in the base tag during this phase. The end mode, in which the base tag is processed a second time. The end mode occurs when ColdFusion reaches the custom tags end tag.
181
182
The baseTag attribute is the name of the base tag that gets access to this tags attributes. The dataCollection attribute is the name of the structure in which the base tag stores the sub-tag data. Its default value is AssocAttribs. You only need to specify a dataCollection attribute if the base tag can have more than one type of sub tag. It is convenient for keeping separate collections of attributes, one per tag type. When cfassociate is encountered in a sub tag, the sub tags attributes are automatically saved in the base tag. The attributes are in a structure appended to the end of an array whose name is 'thisTag.collectionName'. The cfassociate tag performs the following operations:
<!--- Get base tag instance data ---> <cfset data = getBaseTagData(baseTag).thisTag> <!--- Create a string with the attribute collection name ---> <cfset collection_Name = "data.#dataCollection#"> <!--- Create the attribute collection, if necessary ---> <cfif not isDefined(collectionName)> <cfset #collection_Name# = arrayNew(1)> </cfif> <!--- Append the current attributes to the array ---> <cfset temp=arrayAppend(evaluate(collectionName), attributes)>
The CFML code accessing sub-tag attributes in the base tag could look like the following:
<!--- Protect against no sub-tags ---> <cfparam Name=thisTag.assocAttribs default=#arrayNew(1)#> <!--- Loop over the attribute sets of all sub tags ---> <cfloop index=i from=1 to=#arrayLen(thisTag.assocAttribs)#> <!--- Get the attributes structure ---> <cfset subAttribs = thisTag.assocAttribs[i]> <!--- Perform other operations ---> </CFLOOP>
183
name. By default, the closest ancestor is returned. If there is no ancestor by the given name or if the ancestor does not expose any data (such as CFIF), an exception is thrown.
184
<!--- output all the contents of the stack a line at a time ---> <cfloop index="loopcount" from="1" to=#listlen(ancestorlist)#> Ancestorlist entry #loopcount# n is #ListGetAt(ancestorlist,loopcount)#<br> </cfloop><br> </cfoutput> <!--- Determine whether youre nested inside a loop ---> <cfset inloop = listfindnocase(ancestorlist,cfloop)> <cfif inloop neq 0> Im running in the context of a CFLOOP tag.<p> </cfif> <!--- Determine whether you are nested inside a custom tag. Skip the first two elements of the ancestor list, i.e., CFIF and the name of the custom tag Im in ---> <cfset incustomtag = > <cfloop index=elem list=#listrest(listrest(ancestorlist))#> <cfif (left(elem, 3) eq cf_)> <cfset incustomtag = elem> <cfbreak> </cfif> </cfloop> <cfif incustomtag neq > <!--- Say you are there ---> <cfoutput> Im running in the context of a custom tag named #inCustomTag#.<p> </cfoutput> <!--- Get the tag instance data ---> <cfset tagdata = getbasetagdata(incustomtag)> <!--- Find out the tags execution mode ---> Im located inside the <cfif tagdata.thisTag.executionmode neq inactive> custom tag code either because it is in its start or end execution mode. <cfelse> body of the tag </cfif> <p> <cfelse> <!--- Say you are lonely ---> Im not nested inside any custom tags. :^( <p> </cfif> </cfif>
3 4
Save the page as nestag2.cfm. Open the file nesttest.cfm in your browser.
185
Description Valid values are "start" and "end." Used for code validation. It distinguishes between custom tags that are called with and without end tags. anything in the body of the tag, including the results of any active content, such as ColdFusion variables and functions. You can process this content as a variable.
GeneratedContent The content that has been generated by the tag. This includes
AssocAttribs
Holds the attributes of all nested tags if you use cfassociate to make them available to the parent tags.
Modes of execution
ColdFusion invokes a custom tag page in either of two modes: Start tag execution End tag execution If an end tag is not explicitly provided and shorthand empty element syntax (<TagName />) is not used, the custom tag page gets invoked only once, in start tag mode. If a tag must have an end tag provided, use thisTag.HasEndTag during start tag execution to validate this. The same CFML page is executed for both the start and end tag of a custom tag.
186
A custom tag page that performs processing in both modes can have the following format:
<cfif thisTag.ExecutionMode is start> <!--- Start tag processing ---> <cfelse> <!--- End tag processing ---> </CFIF>
187
output generated during start tag processing is not considered part of the tags generated content. As an example, consider a tag that comments out the HTML generated by its descendants. Its implementation could look something like this:
<cfif thisTag.ExecutionMode is end> <cfset thisTag.GeneratedContent = <!--#thisTag.GeneratedContent#-->> </cfif>
Local tags
The ColdFusion engine first searches for a custom tag in the directory of the calling page. This allows you to keep a custom tag file in the same directory as the page that uses it.
Shared tags
To share a custom tag among applications in multiple directories, place it in the Custom Tags folder under your ColdFusion installation directory, for example C:\CFUSION\CustomTags. You can create subfolders to organize custom tags. ColdFusion searches recursively for the Custom Tags directory, stepping down through any existing subdirectories until the custom tag is found.
188
name
attributes
189
The following table describes the options: Option input file output file Description Name of the file you want to encode. cfencode does not process an encoded file. Path and filename of the output file. Warning: If you do not specify an output filename, a warning message asks if you want to continue, in which case the encoded file will overwrite the source file. Recursive, when used with wildcards, recurses through subdirectories to encode files. Suppresses warning messages. Header, allows custom header to be written to the top of the encoded file(s). Required parameter that allows encoding using a specified version number. Use "1" for pages you want to be able to run on ColdFusion 3.x. Use "2" for pages you want to run strictly on ColdFusion 4.0 and later.
/r /q /h /v
Note While it is possible to encode binary files with cfencode, it is not recommended.
190
Chapter 11
ColdFusion includes many tools and techniques for ensuring that your code works properly. These tools include sophisticated debugging and code validation tools, error logging tools, and error handling mechanisms. This chapter describes these tools and presents approaches to troubleshooting common problems. ColdFusion Studio also provides interfaces for debugging application pages and for dynamically validating multiple levels of HTML and CFML code. This chapter does not discuss debugging in ColdFusion Studio.
Contents
Debug Settings in the ColdFusion Administrator................................................. 192 CFML Code Validation............................................................................................ 194 Troubleshooting Common Problems .................................................................... 195 Error Handling in ColdFusion ................................................................................ 197 Generating Custom Error Messages with cferror ................................................. 199 Logging Errors ......................................................................................................... 202 Handling Exceptions in ColdFusion ...................................................................... 204
192
Note If you do not restrict access to debugging information, any browser can use this parameter to get debugging information. To restrict access to specific IP addresses, use the Debugging IPs page of the ColdFusion Administrator to specify the addresses that can receive debugging messages.
When this query runs, it places the debug information into the output page where the query is placed.
Error messages
If ColdFusion is unable to fulfill a request because of an error, it displays a diagnostic message in the users browser. The message includes a link that allows the user to e-mail a report of the error to the site administrator. You enable the mail link feature in the Mail Logging page of the ColdFusion Administrator. Errors are written to a log file for later review.
193
ColdFusion returns the following information: Database errors, including the ODBC error code, the extended error message returned from the ODBC driver, the name of the data source, and the SQL statement submitted to the database Syntax error, including the line of the application page file on which the error occurred System-related errors, such as out of memory conditions, or file or disk access errors You must select the Display the template path in error messages option on the ColdFusion Administrator Debug Options page to include the path of the page that encounters the problem in each error message. Tip If you get a message that does not explicitly identify the cause of the error, check on key system parameters such as available memory and disk space. For information on using the Logging settings and Mail Logging settings, see Advanced ColdFusion Administration
194
Runtime validation
The ColdFusion Application Server features two modes of attribute checking for processing application pages: strict and relaxed. Macromedia recommends that you always use the strictest possible level of CFML validation. To enable strict validation: 1 2 Open the ColdFusion Administrator Server Settings page. Select the Enable Strict Attribute Validation check box.
The code validator inspects all code and validates most attributes before execution begins, when the CFML is converted into executable pseudocode. However, tags with a switch attribute, such as action or method, for which the value is provided at runtime, are validated during execution. Validation of such attributes causes a slight performance penalty. Although dynamically providing an action can save a few lines of code, you should avoid this practice in the interest of a more complete validation and faster application performance. Tip If a commercially purchased custom tag fails to run, try turning off the Enforce Strict Attribute Validation setting in the ColdFusion Administrator. If the tag continues to generate errors, you should contact the tags vendor.
Note The CFML syntax checker cannot detect an invalid attribute combination for attributes whose values are provided at runtime because it does not execute the CFML page it checks.
195
HTTP/URL
Problem: ColdFusion cannot correctly decode the contents of your form submission. The method attribute in forms sent to the ColdFusion Server must be Post, for example:
<form action="test.cfm" method="Post">
Problem: The browser complains when you include spaces in URLs. URLs cannot have embedded spaces. Use a plus sign (+) wherever you want to include a space. ColdFusion correctly translates the + sign into a space. A common scenario in which this error occurs is when you dynamically generate your URL from database text fields that have embedded spaces. To avoid this problem, include only numeric values in the dynamically generated portion of URLs. Or, you can use the URLEncodedFormat function, which automatically replaces spaces with + signs.
196
Problem: Invalid attribute or value. If you use an invalid attribute or attribute values, ColdFusion returns an error message. To prevent such syntax errors, use the ColdFusion syntax validation tools in ColdFusion Studio. Problem: Mismatched quotes and escape characters. Check strings in attributes and expressions for proper placement of single and double quotes. Color coding in ColdFusion Studio can help you spot improper quote placement. Problem: You suspect that there are problems with the structure or contents of a complex data variable, such as a structure, array, query object, or WDDX-encoded variable. Use the cfdump tag to generate a table-formatted display of the variables structure and contents. For example, to dump a structure named relatives, use the following line. Note that you must surround the variable name with pound signs.
<cfdump var=#relatives#>
197
198
Note If the current tag is nested inside other tags, the CFML processor checks the entire stack of open tags until it finds a suitable cftry/cfcatch combination or reaches the end of the stack.
199
Exception Request
Monitor
You set the custom error application pages with the cferror tag. You can set the custom error application pages page-by-page, but because custom error pages generally apply to an entire application, it is more efficient to include the cferror tag in the Application.cfm file. After you create a custom error page, you must include the cferror tag in your applications Application.cfm page. For more information, see Understanding the Web Application Framework on page 214. For detailed information on the cferror tag, see the CFML Reference.
200
Description The exception type. For a list of error types, see Types of recoverable exceptions supported on page 205. Detailed error diagnostics from ColdFusion Server. E-mail address of administrator who should be notified (corresponds to the value set in the mailTo attribute of cferror). Date and time when the error occurred. Browser that was running when the error occurred. content.
error.diagnostics error.mailTo
error.dateTime error.browser
IP address of the remote client. Page from which the client accessed the link to the page where the error occurred. Page being executed when the error occurred. URL query string of the client's request.
error.template error.queryString
201
Error variable
Description message.
Unordered list of validation errors that occurred. This includes any text that you specify in the value attribute or a hidden tag used to validate form input. message.
202
Logging Errors
ColdFusion Server provides extensive capabilities for generating, managing, and viewing log files, as described in Advanced ColdFusion Administration. ColdFusion automatically logs errors to the default logs in the following cases: If you use the default error handlers If a cferror handler of type Request handles the error Otherwise you must use the cflog tag in your error handling code to generate log entries. The cflog tag lets you specify the following information: A custom file or standard ColdFusion log file in which to write the message. Text to write to the log file. Message severity (type): Information Warning, Fatal, or Error. Whether to log any of the following: application name, thread ID, system date, or system time. By default, all get logged. For example, you could use a cflog tag in an exception error page to log the error information to an application-specific log file.
<html> <head> <title>Products - Error</title> </head> <body> <h2>Sorry</h2> <p>An error occurred when you requested this page. The error has been logged and we will work to correct the problem.
Logging Errors
203
We apologize for the inconvenience. </p> <cflog file="myapp_errors" text="Exception error -Exception type: #error.type# Template: #error.template#, Remote Address: #error.remoteAddress#, HTTP Rerference: #error.HTTPReferer# Diagnositcs: #error.diagnostics#" type="Error"> </body> </html>
Description When this page is processed, log an error message to the file myapp_errors.log file in the ColdFusion log directory containing the thread ID, date and time, application, and an error message that includes the exception type, the path of the page that caused the error, the remote address that called the page, and the errors diagnostic message.
204
To catch errors in a single problematic SQL statement, for example, you might narrow the focus by surrounding the ColdFusion tag that contains the SQL statement with a cftry block and following it with a cfcatch type="Database" tag that displays the information in the cfcatch.SQLState variable. Note Do not attempt to enclose an entire application in a cftry block by putting the cftry tag in Application.cfm because you cannot be sure that there always will be a matching cftry end tag. For information on the cftry, cfcatch, cfrethrow, and cfthrow tags, see the CFML Reference.
205
Notes Catch failed database operations, such as failed SQL statements, ODBC problems, and so on. Catch general application page errors. The cfinclude, cfmodule, and cferror tags can generate a template exception. missing.
Template errors
cfcatch type="Template"
cfcatch type="missingInclude" Catch errors where included files are cfcatch type="Object" cfcatch type="Security"
Catch exceptions in ColdFusion code that works with objects. Raise catchable exceptions in ColdFusion code that works with security. Catch exceptions when an expression fails evaluation. Catch failed locking operations, such as when a cflock critical section times out or fails at runtime. Catch only those custom exceptions that are specified as having the Application type in the cfthrow tag that defines them.
Application-defined exception events raised by cfthrow Custom exceptions raised by cfthrow Unspecified exceptions
cfcatch Catch a custom a exception type raised by type="custom_exception_type" cfthrow. cfcatch type="Any"
Catch any exceptions that are not specifically handled in another error handler, including unexpected internal errors.
Specifying the type as any causes the ColdFusion Application Server to catch internal exceptions, memory allocation errors, and access violations, which you might not be prepared to handle.
206
Applications can optionally use the cfthrow tag to raise custom exceptions. Such exceptions are caught with any of the following type specifications: type="custom_exception_type" type="application" type="any" The custom_exception_type type designates the name of a user-defined type specified in the cfthrow tag. An exception raised within a cfcatch block cannot be handled by the cftry block that immediately encloses the cfcatch tag.
Description The exceptions type, returned as a string. The exceptions diagnostic message, if one was provided. If no diagnostic message is available, this is an empty string. A detailed message from the CFML interpreter. This message, which contains HTML formatting, can help to determine which tag threw the exception. A custom error message. This is returned only for cfcatch tags where type="Application" or a custom type. Any exception that is a part of the CFML exception hierarchy supplies a value for this variable. For type="Application", cfthrow tags can supply a value for this code via the errorcode attribute. For Type="Database", cfcatch.errorcode has the same value as cfcatch.sqlstate. Otherwise, the value of cfcatch.errorCode is the empty string. Provides the name and position of each tag in the tag stack and the full pathnames of the files that contain the tags in the tag stack.
cfcatch.detail
cfcatch.extendedInfo cfcatch.errorCode
cfcatch.tagContext
207
The structure at position 1 of the array represents the outermost tag in the stack of tags that were executing when the interpreter detected the exception. The structure at position ArrayLen(cfcatch.tagContext) represents the currently executing tag at the time the interpreter detected the exception. The tagContext structures have the following attributes: Template The pathname of the application page that contains the tag. Line and Column The tags line number and column number within the application page. Note Clear the Enable CFML stack trace option to avoid having production servers expend resources creating a traceback stack by default. When you turn off this setting, cfcatch.tagContext is a zero-length array.
Database exceptions
The following additional variables are available whenever the exception type is database: Property variable
cfcatch.nativeErrorCode
Description The native error code associated with this exception. Database drivers typically provide error codes to assist in the diagnosis of failing database operations. The values assumed by cfcatch.NativeErrorCode are driver-dependent. If no error code is provided, the value of nativeErrorCode is -1. The SQLState code associated with this exception. Database drivers typically provide error codes to assist in the diagnosis of failing database operations. The values assumed by cfcatch.SQLState are driver-dependent. If no SQLState value was provided, the value of SQLState is -1.
cfcatch.SQLState
Expression exceptions
The following variable is only available for expression exceptions: Property variable
cfcatch.errnumber
208
Locking exceptions
The following additional information is available for exceptions related to cflock sections: Property variable
cfcatch.lockName cfcatch.lockOperation
Description The name of the affected lock. This is set to "anonymous" if the lock name is unknown. The operation that failed. This is set to "unknown" if the failed operation is unknown.
If an exception occurs during the cfquery statements execution, the application page flow switches to the cfcatch type="Database" exception handler. It then resumes with the next statement after the cftry block, once the cfcatch type="Database" handler completes. Similarly, the cfcatch type="MissingInclude" block handles exceptions raised by the cfinclude tag. Any unknown, but possibly recoverable, exceptions are handled by the cfcatch type="Any" block.
209
<!--- Wrap code you want to check in a cftry block ---> <cfset EmpID=3> <cftry> <cfquery name="test" datasource="CompanyInfo"> SELECT Dept_ID, FirstName, LastName FROM Employee WHERE Emp_ID=#EmpID# </cfquery> <html> <head> <title>Test cftry/cfcatch</title> </head> <body> <hr> <cfinclude template="includeme.cfm"> <cfoutput query="test"> <p>Department: #Dept_ID#<br> Last Name: #LastName#<br> First Name: #FirstName#</p> </cfoutput> <hr> <!--- Use cfcatch to test for missing included files. ---> <!--- Print Message and Detail error messages. ---> <!--- Block executes only if a MissingInclude exception is thrown. ---> <cfcatch type="MissingInclude"> <h1>Missing Include File</h1> <cfoutput> <ul> <li><b>Message:</b> #cfcatch.Message# <li><b>Detail:</b> #cfcatch.Detail# <li><b>File name:</b> #cfcatch.MissingFilename# </ul> </cfoutput> </cfcatch> <!--- Use cfcatch to test for database errors.---> <!--- Print error messages. ---> <!--- Block executes only if a Database exception is thrown. ---> <cfcatch type="Database"> <h1>Database Error</h1> <cfoutput> <ul> <li><b>Message:</b> #cfcatch.Message# <li><b>Native error code:</b> #cfcatch.NativeErrorCode# <li><b>SQLState:</b> #cfcatch.SQLState# <li><b>Detail:</b> #cfcatch.Detail# </ul> </cfoutput>
210
</cfcatch> <!--- Use cfcatch with TYPE="Any" ---> <!--- to find unexpected exceptions. ---> <cfcatch type="Any"> <cfoutput> <h1>Other Error: #cfcatch.Type#</h1> <ul> <li><b>Message:</b> #cfcatch.message# <li><b>Detail:</b> #cfcatch.Detail# </ul> </cfoutput> </cfcatch> </cftry> </body> </html>
to:
FROM Employer
Display the page. This time the cfcatch type="Database" block displays an error message. 4 Correct Employer back to Employee. Change the cfoutput line:
<p>Department: #Dept_ID#<br>
to:
<p>Department: #DepartmentID#<br>
Display the page. This time the cfcatch type="Any" block displays an error message indicating an expression error.
211
Naming conventions
A naming convention for custom exception types follows a convention that is similar to Java class naming conventions: domain name in reverse order, followed by project identifiers, as in this example:
<cfthrow type="Invalid_field.codeValue" errorcode="Dodge14B">
The predefined exception types, except for type="Application", are reserved; for example, <cfthrow type="Database"> will be rejected. A cfcatch tag can specify a custom type as well as one of the predefined types. For example, to catch the exception thrown above, you use this syntax:
<cfcatch type="Invalid_field.codeValue">
ColdFusion uses the catch type as a pattern to find a catch handler. For example,
<cfthrow type="MyApp.BusinessRuleException.InvalidAccount">
The handler that matches most exactly handles the error. Therefore, in this case, the MyApp.BusinessRuleException.InvalidAccount handler gets invoked. However, if you used the following cfthrow tag:
<cfthrow type="MyApp.BusinessRuleException.InvalidVendorCode
the MyApp.BusinessRuleException handler receives the error. The type comparison is case-insensitive. To match types exactly, rather than performing pattern matching, use the cfsetting attribute catchExceptionsByPattern="No".
212
Chapter 12
The ColdFusion Web Application Framework is a powerful tool that you can use to help structure your ColdFusion applications. This chapter describes how to create and use the Application.cfm file, the application page that controls the application framework.
Contents
Understanding the Web Application Framework ................................................. 214 Mapping an Application Framework..................................................................... 216 Creating the Application.cfm File .......................................................................... 219 Managing the Client State ...................................................................................... 221 Configuring and Using Client Variables ................................................................ 223 Using Session Variables .......................................................................................... 228 Using Application Variables ................................................................................... 230 Using Server Variables ............................................................................................ 232 Locking Code with cflock........................................................................................ 233 Examples of cflock................................................................................................... 238
214
Session
215
Variable Scope Description Application Contains variables that are available to all pages in an application for all clients. Application variables are stored in memory and time out after a period of inactivity or when the server shuts down. You can access the Application scope as a data structure. You must use the Application scope prefix in the variable name. Contains variables that are available to all applications in a server and all clients. Server variables are stored in memory. They do not time out, and are only deleted when the server stops running. You cannot access the Server scope as a data structure. You must use the Server scope prefix in the variable name.
Server
ColdFusion does not attempt to automatically evaluate Application, Session, or Server variables. You must use variable prefixes with these variables, as in Session.variablename or Application.variablename. As a general rule you should prefix all these variables with their scope identifier. ColdFusion provides locking functions to manage access to Session, Application, and Server variables. Because these variables are kept in your servers memory, you must lock them when you use them to prevent errors that arise from simultaneous access. Caution Understanding lock management and using locks effectively is vital to correctly using Session, Application, and Server scope variables. For more information on locking, see Locking Code with cflock on page 233.
216
Processing Application.cfm
When any ColdFusion application page is requested, ColdFusion searches up the pages directory tree for an Application.cfm file. When it is found, the Application.cfm code is logically included at the beginning of that page. If it is not found, ColdFusion searches up the directory tree until it finds an Application.cfm file. If more than one Application.cfm file is in the current directory tree, ColdFusion uses the first one it finds. Only one Application.cfm file is ever processed for each ColdFusion application page. The Application.cfm file is automatically included in each application page, as if by a cfincludetag. If the Application.cfm page it is present in the directory tree, there is no way not to include it. For this reason, it is the ideal location to set application-level variables. If an application page has a cfinclude tag pointing to an additional application page, ColdFusion does not initiate another search for an Application.cfm page when it includes the additional page. If your application runs on a UNIX platform, which is case sensitive, you must spell Application.cfm with an initial capital letter.
Processing OnRequestEnd.cfm
Just as the Application.cfm file is executed before each application page it governs, you can specify a file named OnRequestEnd.cfm, which is executed after each application page in the same application. ColdFusion Server looks for the OnRequestEnd.cfm file in the same directory as the Application.cfm file of the current application page. The OnRequestEnd.cfm file is never executed if it resides in another directory. The OnRequestEnd.cfm file is not executed if there is an error or an exception in the called page, or if the called page executes the cfabortor cfexit tag. Just as the Application.cfm file must be spelled with a capital A on UNIX systems, you must spell the OnRequestEnd.cfm file with capital O, R, and E.
217
218
219
Save the file as Application.cfm in the root directory of your application framework.
220
Example: Application.cfm
The following example shows a complete Application.cfm file for the sample Products application:
<!--- Set application name and enable Client variables, stored in a data source called mycompany ---> <cfapplication name="Products" clientmanagement="Yes" clientstorage="mycompany" sessionmanagement="Yes"> <!--- Set custom global error handling pages for this application---> <cferror type="REQUEST" template="requesterr.cfm" mailto="[email protected]"> <cferror type="VALIDATION" template="validationerr.cfm"> <!--- Set application-specific constants. These are put in the Variables scope of every page in the application---> <cfset homepage="http://www.mycompany.com"> <cfset primarydatasource="CompanyDB"> <!--- set global error handling for this application ---> <!--- set Session variable for this application.---> <!--- Note that the cfset tag is surrounded by a cflock tag ---> <cflock timeout="30" scope="Session" type="exclusive"> <cfset session.current_location = "Davis, Porter, Alewife"> </cflock> <cfset mainpage = "default.cfm"> <cfset sm_location = "dpa"> <cfset current_page = "#cgi.path_info#?#cgi.query_string#">
221
Session
As a general rule, it is best to use Session variables for any values that need to exist for only a single browser session. You should reserve Client variables for client-specific data that you want available for multiple browser sessions, such as client preferences.
222
223
Save the file as Application.cfm in the root directory of your application framework.
Cookie storage
When you set clientstorage="Cookie" the cookie that ColdFusion creates has the applications name. Storing client data in a cookie is scalable to large numbers of clients, but this storage mechanism has some limitations. Chief among them is that if the client turns off cookies in the browser, Client variables do not work.
224
Consider these additional limitations before implementing cookie storage for Client variables: Many browsers allow only 20 cookies from a particular host to be set. ColdFusion uses two of these cookies for CFID and CFToken and also creates a cookie named cfglobals to hold global data about the client, such as HitCount, TimeCreated, and LastVisit. This limits you to 17 unique applications per host. Some browsers set a size limit of 4K bytes per cookie. ColdFusion encodes nonalphanumeric data in cookies with a URL encoding scheme that expands at a 3-1 ratio, which means you should not store large amounts of data per client. ColdFusion throws an error if you try to store more than 4000 encoded bytes of data for a client.
Save the file as Application.cfm in the root directory of your application framework.
Note Client storage mechanisms are exclusive; when one storage type is in use, the values set in other storage options are unavailable.
After you set a Client variable in this manner, it is available for use within any page in your application that is accessed by the client for whom the variable is set.
225
The following example shows how to use the cfparam tag to check for the existence of a client parameter and to set a default value if the parameter does not already exist:
<cfparam name="Client.FavoriteColor" default="Red">
Description The client ID, normally stored on the client system as a cookie. The client security token, normally stored on the client system as a cookie. A combination of the CFID and CFToken in the form CFID=IDNum&CFTOKEN=tokenNum. This variable is useful if the client does not support cookies and you must pass the CFID and CFToken variables from page to page. The number of page requests made by the client. The last time the client visited the application. client to ColdFusion were first created.
Client.HitCount Client.LastVisit
Client.TimeCreated The time the CFID and CFToken variables that identify the
You can use the Client.HitCount and time information variables in customizing behavior, depending on how often users visit your site and when they last visited. For example, the following code shows the date of a users last visit to your site:
<cfoutput> Welcome back to the Web SuperShop. Your last visit was on #DateFormat(Client.LastVisit)#. </cfoutput>
226
The GetClientVariablesList function returns a comma-separated list of the names of the Client variables for the current application. The standard system-provided Client variables (CFID, CFToken, URLToken, HitCount, TimeCreated, and LastVisit) are not returned in the list.
The DeleteClientVariable function deletes only Client variables for the application specified by cfapplication, if any. For more information on this function, see the CFML Reference. Also, using the Client Variables page of the ColdFusion Administrator Server tab, you can edit the Client variable storage to remove Client variables stored in either the Registry or a database after a set number of days. (The default value is 90 days when Client variables are stored in the registry, 10 days when stored in a data source.) For more information about setting timeout values, see Advanced ColdFusion Administration. Note You cannot delete the system-provided Client variables (CFID, CFToken, URLToken, HitCount, TimeCreated, and LastVisit).
227
3 4
On the Registry menu, click Export Registry File. Enter a name for the registry file.
After you create a registry file, you can copy it to a new machine and import it by selecting Import Registry File on the Registry Editor Registry menu. On UNIX systems, the registry entries are kept in /opt/coldfusion/registry/ cf.registry, a text file that you can copy and edit directly.
228
What is a session?
A session refers to all the connections that a single client might make to a server in the course of viewing any pages associated with a given application. Sessions are specific to individual users. As a result, every user has a separate session and has access to a separate set of Session variables. This logical view of a session begins with the first connection by a client and ends (after a specified timeout period) after that clients last connection. However, because of the stateless nature of the Web, it is not always possible to define a precise point at which a session ends. In the real world, a session ends when the user finishes using an application. In most cases, however, a Web application has no way of knowing if a user is finished or just lingering over a page. You can impose some structure on Session variable duration by specifying a timeout period. If the user does not access a page of the application within this timeout period, ColdFusion interprets this as the end of the session and clears any variables associated with that session.
229
The default timeout for Session variables is set to 20 minutes. You can change the timeout on the Memory Variables page of the ColdFusion Administrator Server tab. For more information, see Advanced ColdFusion Administration. You can also set the timeout period for Session variables inside a specific application (thereby overruling the Administrator default setting) by using the cfapplication tag sessionTimeout attribute.
Description The client ID, normally stored on the client system as a cookie. The client security token, normally stored on the client system as a cookie. A combination of the CFID and CFToken in the form CFID=IDNum&CFTOKEN=tokenNum. Use this variable if the client does not support cookies and you must pass the CFID and CFToken variables from page to page. A unique identifier for the session. You use this variable in cflock tags to identify the scope of the lock.
Session.SessionID
If you are also using Client variables, the Session.CFID, Session.CFToken, and Session.URL token are identical to the corresponding Client variables.
230
231
variables, they are not useful for client-specific information. To target variables for specific clients, use Session or Client variables.
232
Server.ColdFusion.ProductVersion The version number for the server that is running, such as 5,0,0 Server.ColdFusion.ProductLevel Server.ColdFusion.SerialNumber Server.ColdFusion.Locales Server.OS.Name Server.OS.AdditionalInformation Server.OS.Version Server.OS.BuildNumber The server product level, such as Enterprise The serial number assigned to this server installation The locales, such as English (US) and Spanish (Mexican), supported by the server The name of the operating system, such as Windows NT Additional information provided by the operating system, such as the Service Pack number The version number of the operating system, such as 4.0 The specific operating system build, such as 1381
233
Using cflock
You protect access to code by surrounding it in a cflock tag; for example:
<cflock scope="Application" timeout="10" type="Exclusive"> <cfif not isdefined("application.number")> <cfset Application.number = 1> </cfif> </cflock>
234
The cflock tag enables you to ensure that concurrently executing requests do not access the same section of code simultaneously and thus manipulate shared data structures, files, or CFXs inconsistently. It is important to remember that cflock protects code sections not variables.
Lock types
The cflock tag offers two modes of locking, specified by the type attribute: Exclusive locks (the default lock type) allow only one request to process the locked code. No other requests are allowed to start running code inside the tag while a request has an exclusive lock. ColdFusion issues exclusive locks on a first-come, first-serve basis. Enclose all code that creates or modifies Session, Application, or Server variables in exclusive cflock tags. Read-only locks allow multiple requests to execute concurrently, provided that no exclusive locks are executing. ColdFusion allows you to set variables inside read-only lock tag blocks. However, if you do set a shared variable inside a read-only lock tag, you lose the advantages of locking. As a result, you must be careful not to set any Session, Application, or Server variables inside a read-only cflock tag body. Enclose code that reads or tests Session, Application, or Server variables in exclusive cflock tags. You specify a read-only lock by setting the type="readOnly" attribute in the cflock tag.
235
You can set the attribute to any of the following values: Scope Server Application Session Meaning All code sections with this attribute on the server share a single lock. All code sections with this attribute in the same application share a single lock. All code sections with this attribute that run in the same session and application share a single lock.
If multiple code sections share a lock, the following rules apply: When code in a cflock tag block with the type Exclusive is running, code in blocks with the same lock are not allowed run. They wait until the code with the Exclusive lock completes. When code in a cflock tag block with the type read-only is running, code in other blocks with the same lock and the read-only type can run, but any blocks with the exclusive type cannot run and wait until all code with the read-only lock completes.
Controlling locking access to files and CFX tags with the name attribute
The cflock name attribute provides a second mechanism for identifying locks. Use this attribute when you use locks to protect code that manges file access or calls non-thread-safe CFX code. When you use the name attribute, specify the same name for each section of code that accesses a specific file or a specific CFX tag.
236
For example, if you want to assign the results of a query to a Session variable, first get the query results using a Variables scope variable in unlocked code. Then, assign the query results to a Session variable inside a locked code section. The following code illustrates this technique:
<cfquery name="Variables.qUser" datasource="#request.dsn#"> SELECT FirstName, LastName FROM Users WHERE UserID = #request.UserID# </cfquery> <cflock scope="Session" timeout="2" type="exclusive"> <cfset Session.qUser = Variables.qUser> </cflock>
No automatic ColdFusion does not check for lock use and does not prevent checking or locking any invalid access of shared variables. Full checking ColdFusion generates an exception error when your application attempts to use any variable in the scope without protecting it with a lock. If your application reads a variable without protecting it, ColdFusion creates a read-only lock for the duration of the read. As a result, ColdFusion blocks any attempt to write to the variable (using code within a lock) until the read completes and the read-only lock is released. If your application writes to any variable in the scope without protecting it with a lock, ColdFusion generates an exception error.
Selecting the No automatic checking or locking option results in the most efficient code, but requires you to follow the full rules of locking. You should only select this option after you finish debugging your program. Full checking is very useful for debugging your code. You get errors to help indicate missing locks. You can leave this feature on in production code to protect against inadvertently unlocked variable accesses, but it adds processor overhead for checking all accesses to shared variables, and all locking problems cause exceptions.
237
Automatic read locking also adds overhead because ColdFusion must insert read locks and check variable access for locking. However, it can be useful if you already have a site that does not use locking properly. In this case, you must only lock all writes and do not have to add locks around all reads.
Single-threading sessions
The ColdFusion Administrator also allows you to specify single-threaded sessions. If you select this option, each session is handled by a single thread in the ColdFusion Server. As a result, one request from the client must complete before the next one can begin. In this case, you do not need to lock Session variables, but the performance of frames-based pages might be reduced because it prevents simultaneous processing of requests from multiple frames.
Once a deadlock occurs, neither of the users can do anything to break the deadlock, because the execution of their requests is blocked until the deadlock is resolved by a lock timeout. In addition, if you nest locks of different types, you can cause a deadlock. An example of this is nesting an exclusive lock inside a read lock of the same scope, or of the same name. In order to avoid a deadlock, you should lock code sections in a well-specified order and name the locks consistently. In particular, if you need to lock access to the Server, Application, and Session scopes, you must do so in the following order. 1 2 3 4 Lock the Session scope. In the cflock tag, specify the scope as "session." Lock the Application scope. In the cflock tag, specify the scope as "application." Lock the Server scope. In the cflock tag, specify the scope as "server." Unlock the Server scope.
238
5 6
Note You can skip any pair of lock/unlock steps in the preceding list if you do not need to lock a particular scope. For example, you can omit steps 3 and 4 if you do not need to lock the Server scope.
Examples of cflock
The following examples show how to use cflock in a variety of situations.
Examples of cflock
239
</cfif> </cflock> <!--- Always display the number of turtlenecks sold ---> <cflock scope="Application" timeout="10" type ="ReadOnly"> <cfoutput> E-Turtleneck is proud to say that we have sold #application.number# turtlenecks to date. </cfoutput> </cflock>
The remaining sample code could appear inside the application page where customers place orders. In this simple example, the Application.cfm page displays the Application.number variable value. Because Application.cfm is processed before any code on each CFML page, the number that displays after you click the submit button does not include the new order. One way you can resolve this problem is by using the OnRequestEnd.cfm page to display the value at the bottom of each page in the application.
<html> <head> <title>cflock Example</title> </head> <body> <h3>cflock Example</h3> <cfif isdefined("form.submit")> <!--- Lock Session variables ---> <!--- Note that we use the automatically generated Session ID as the order number ---> <cflock scope="Session" timeout="10" type="ReadOnly"> <cfoutput>Thank you for shopping E-Turtleneck. Today you have chosen a turtleneck in size <b>#form.size#</b> and in the color <b>#form.color#</b>. Your order number is #session.sessionID#. </cfoutput> </cflock> <!--- Lock Session variables to assign form values to them. To lock Session variables, you should get the session ID with the sessionID member variable. ---> <cflock scope="Session" timeout="10" type="Exclusive"> <cfparam name=session.size default=#form.size#> <cfparam name=session.color default=#form.color#> </cflock>
240
<!--- Lock Application Variable application.number to update the total number of turtlenecks sold. ---> <cflock scope="Application" timeout="30" type="Exclusive"> <cfset application.number=application.number + 1> </cflock> <!--- Show the form only if it has not been submitted. ---> <cfelse> <form action="cflock.cfm" method="Post"> <p> Congratulations! You have just selected the longest wearing, most comfortable turtleneck in the world. Please indicate the color and size you want to buy.</p> <table cellspacing="2" cellpadding="2" border="0"> <tr> <td>Select a color.</td> <td><select type="Text" name="color"> <option>red <option>white <option>blue <option>turquoise <option>black <option>forest green </select> </td> </tr> <tr> <td>Select a size.</td> <td><select type="Text" name="size"> <option>small <option>medium <option>large <option>xlarge </select> </td> </tr> <tr> <td></td> <td><input type="Submit" name="submit" value="Submit"> </td> </tr> </table> </form> </cfif> </body> </html>
Examples of cflock
241
242
Chapter 13
ColdFusion offers a server-side scripting language, CFScript, that provides ColdFusion functionality in script syntax. This JavaScript-like language gives developers the same control flow, but without tags. You can also use CFScript to write custom functions that you can use anywhere a ColdFusion expression is allowed. This chapter describes the CFScript languages functionality and syntax.
Contents
About CFScript ........................................................................................................ 244 The CFScript Language........................................................................................... 245 Interaction of CFScript with CFML........................................................................ 249 Defining and Using Custom Functions ................................................................. 250
244
About CFScript
The ColdFusion Server-side scripting language, CFScript, offers ColdFusion functionality in script syntax. This JavaScript-like language offers the same control flow, but without tags. CFScript regions are bounded by <cfscript> and </cfscript> tags. You can use ColdFusion expressions, but not CFML tags, inside a CFScript region.
CFScript example
The following example shows how you can rewrite a block of cfset tags in CFScript:
Using CFScript
<cfscript> employee=StructNew(); employee.firstname=Form.firstname; employee.lastname=Form.lastname; employee.email=Form.email; employee.phone=Form.phone; employee.department=Form.department; WriteOutput("About to add " & Form.firstname & " " & Form.lastname); </cfscript>
The WriteOutput function appends text to the page output stream. Although you can call this function anywhere within a page, it is most useful inside a cfscript block. For information on the WriteOutput function, see the CFML Reference.
Supported statements
CFScript supports the following statements: if-else for for-in return (in custom functions only) while break switch-case do-while continue var (in custom functions only)
245
Comments
Comments in CFScript blocks begin with two forward slashes (//) and end at the line end. You can also enclose CFScript comments between /* and */. Note that you cannot nest /* and */ inside other comment lines.
Variables
Variables can be of any ColdFusion type, such as numbers, strings, arrays, queries, and COM objects. You can read and write variables within the script region.
Expressions
CFScript supports all CFML expressions. CFML expressions include operators (such as +, -, EQ, and so on), as well as all CFML functions. For information about CFML expression, operators, and functions, see the CFML Reference.
Note
You cannot use CFML tags in CFScript.
Statements
In CFScript, semicolons define the end of a statement. Line breaks are insignificant. Enclose multiple statements in curly braces to group them for use in an expression:
{ statement; statement; statement; }
Assignment: lval = expr ; lval can be a simple variable, an array reference, or a member of a structure. For example:
x = "positive"; y = x; a[3]=5; structure.member=10;
246
for loop: for (init-expr ; test-expr ; final-expr) statement ; init-expr and final-expr can be one of the following: A single assignment expression, for example, x=5 or loop=loop+1 Any ColdFusion expression, for example, SetVariable("a",a+1) Empty The test-expr can be one of the following: Any ColdFusion expression, for example, A LT 5, loop LE x, or Y EQ "not found" AND loop LT end Empty Here are some examples of for loops:
for(Loop=1; Loop LT 10; Loop = Loop + 1) a[loop]=loop;
// Complete for loop in a single line. for(loop=1; loop LT 10; loop=loop+1)a[loop]=loop; // Use braces to indicate multiple statements to loop over for( ; ; ) { indx=indx+1; if(Find("key",strings[indx],1)) break; }
247
switch-case: switch (expr) {case constant : statement break ; default : statement } In this syntax, constant must be a constant (that is, not a variable, a function, or other expression). Only one default statement is allowed. You can use multiple case statements. You cannot mix Boolean and numeric case values in a switch statement. No two constants can be the same inside a switch statement.
switch(name) { case "John": { male=true; found=true; break; } case "Mary": { male=false; found=true; break; } default: { found=false; break; } } //end switch
for-in loop: for (variable in collection) statement ; variable can be any ColdFusion identifier, and collection must be the name of an existing ColdFusion structure.
for (x in mystruct) mystruct[x]=0;
248
return, var: See Defining and Using Custom Functions on page 250
Reserved words
In addition to the names of ColdFusion functions and words reserved by ColdFusion expressions (such as NOT, AND, IS, and so on), the following words are reserved in CFScript. Do not use these words as variables or identifiers in your scripting code: for else default var while switch in return do case continue if break function
Note
CFScript is not directly exportable to JavaScript. Only a limited subset of JavaScript can run inside CFScript.
249
250
Defining functions
You define functions using CFScript, in a manner similar to defining JavaScript functions. The function must return a value. Functions can be recursive, that is, the body of a function can call the function. You can define a function in the following places: On the page where it is called (even after it is called, although this is not recommended). 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 applications functions on a single page and place a cfinclude tag at the top of pages that use the functions. Syntax Use the following syntax inside a cfscript tag to define a function: function functionName( [paramName1[, paramName2...]] ) { CFScript Statements } functionName The name of the function. You cannot use the name of an standard ColdFusion function name. You cannot use the same name for two different function definitions. Function names cannot include periods. paramName1... Names of the parameters required by the function. The number of arguments passed into the function must equal or exceed the number of parameters in the function definition. If the calling page omits any of the required parameters, ColdFusion generates a mismatched argument count error. The body of the function definition must consist of one or more valid CFScript statements.
251
The following two statements are allowed only in function definitions. Each function must have a return statement: var variableName = initialValue; Creates and initializes a variable that is local to the function (function variable). This variable has meaning only inside the function and is not saved between calls to the function. It has precedence in the function body over any variables with the same name that exist in any other scopes. You never prefix a function variable with a scope identifier, and their names cannot include periods. All var statements must be at the top of the function declaration, before any other statements. You must initialize all variables when you declare them. You cannot use the same name for a function variable and a parameter. return expression; Evaluates expression, returns its value to the page that called the function, and exits the function. You can return any valid ColdFusion variable type, including structures, queries, and arrays. Each function must execute a return statement.
Calling functions
You can call a function anywhere that you can use an expression, including in the body of a cfoutput tag, in a ColdFusion Script, or in a tag attribute value. One function can call another function, and you can use a function as a parameter to another function. You call custom functions the same way you call any built-in ColdFusion functions.
252
Each function has a built-in Arguments array containing all arguments passed to the function: the required arguments specified by the function parameters followed by any additional arguments included in the function call. The function can determine the number of arguments passed to it by using the ColdFusion function call ArrayLen(Arguments). The function must retrieve the optional arguments by using the Arguments array. For example, if the following function:
function MyFunction(MyArg1, MyArg2)
has three optional arguments, you can refer to the first two, required, arguments as MyArg1 and MyArg2 or as Arguments[1] and Arguments[2]. You must refer to the third and fourth and fifth, optional, arguments as Arguments[3], Arguments[4], and Arguments[5]. However, you must be careful if you mix references to the same argument using both its parameter name and its place in the Arguments array. Mixing is fine if all you do is read the argument. If you write the argument, you should consistently use either the parameter name or the Arguments array.
Passing arguments
ColdFusion passes arrays and simple data types including integers, strings, and time and date values into the function by value. It passes queries and structures into the function by reference. As a result, if you change the value of a query or structure argument variable in the function, it changes the value of the variable that the calling page used in calling the function. However, if you change the value of an array or string argument variable in the function, it does not change the value of the string variable in the calling page.
Using variables
A function can access all variables that are available in the calling page. In addition, the function has its own private scope that contains the function parameters, the Arguments array, and the var-declared variables. This scope is only accessible inside the current instance of the function. As soon as the function exits, all the variables are removed. A function can use and change any variable that is available in the calling page, including variables in the callers Variables (local) scope, as if the function were part of the calling page. For example, if you know that the calling page has a local variable called Customer_name (and there is no var variable named Customer_name) the function can read and change the variable by referring to it as "Customer_name" or (using better coding practice) "Variables.Customer_name". Similarly, you can create a local variable inside a function and then refer to it anywhere in the calling page after the function call. You cannot refer to the variable before you call the function. Because function var variables do not take a scope identifier and exist only while the function executes, function variable names can be independent of variable names
253
used elsewhere in your application. If a function must use a variable from another scope that has the same name as a function variable, just prefix the external variable with its scope identifier, such as Variables or Form. For example, if you use the variable name x for a function scope (var) variable and for a Variables scope (local) variable in the body of a page that calls the function, the two variables are independent of each other. You cannot refer to the function variable in the body of the page, but you can refer to the local variable in the function as Variables.x.
Note that the you do not surround the argument to IsCustomFunction in quotation marks.
254
You could use the TotalInterest function in a cfoutput tag of a forms action page as follows:
<cfoutput> Loan amount: #Form.Principal#<br> Annual percentage rate: #Form.AnnualPercent#<br> Loan duration: #Form.Months# months<br> TOTAL INTEREST: #TotalInterest(Form.Principal, Form.AnnualPercent, Form.Months)#<br> </cfoutput>
Example 2
This function shows the use of optional arguments. It takes two or more arguments and adds them together.
<cfscript> function Sum2(a,b) { var sum = a + b; var arg_count = ArrayLen(Arguments); var opt_arg = 3; for( ; opt_arg LTE arg_count; opt_arg = opt_arg + 1 ) { sum = sum + Arguments[opt_arg]; } return sum; } </cfscript>
Using Application.cfm
Consider putting custom functions that you use frequently on the Application.cfm page.
255
You can use functions that manipulate many rows of a query outside such tags. There you can pass in a query and loop over it in the function. The following example, which changes text in a query column to uppercase, illustrates using a function to modify multiple query rows.
function UCaseColumn(myquery, colName) { var currentRow = 1; for (; currentRow lte myquery.RecordCount; currentRow = currentRow + 1) { myquery[colName][currentRow] = UCase(myquery[colName][currentRow]); } }
256
function makes using the structure appears, but the change the function makes using the directly passed array does not affect the array outside the function.
<CFScript> //Create a two-element array inside a structure mystruct = StructNew(); mystruct.myarray = ArrayNew(1);; mystruct.myarray[1] = "This is the original element one"; mystruct.myarray[2] = "This is the original element two"; //Define a custom function to manipulate both //an array in a structure (using struct_param) and //an array that is passed directly (using array_param). function setarray( struct_param, array_param ) { //Change the first element of the array passed in the structure struct_param.myarray[1] = "This is the NEW element one"; //Change the seond element of the directly-passed array array_param[2] = "This is the NEW element two"; return "success"; } //Call the function passing the structure and the array setarray( mystruct, mystruct.myarray); </CFScript> <CFOutput> <!--- The element one is changed ---> <br>#mystruct.myarray[1]# <!--- Element two is unchanged because the function got a copy ---> <br>#mystruct.myarray[2]# </CFoutput>
Error handling
You can handle errors in custom functions by writing a status variable indicating success or failure and some information about the failure. You can also return a special value to indicate failure. The following sketch outlines possible combinations of both these approaches:
function bigCalc(x, y, errorInfo) { // Clear error state // This allows errorInfo struct to be reused structClear(errorInfo); var isOK = true; // Do work, populate fields in errorInfo such as // errorNumber, errorMsg, errorDetail, whatever ... if (isOK) { return calculatedValue;
257
} else { // Need to return error value // Caller will look at value and then decide to look at errorInfo // Alternatively, caller can look at errorInfo and see whether // some pre-defined fields are available return -1; // or "" or whatever we have agreed to... } } errorInfo = structNew(); result = bigCalc(x, y, errorInfo); if (result eq -1) { // use information from errorInfo }
258
Chapter 14
This chapter describes how regular expressions work in the following ColdFusion functions: REFind REFindNoCase REReplace REReplaceNoCase This chapter does not apply to regular expressions used in the cfinput and cftextinput tags. These tags use JavaScript regular expressions, which have a slightly different syntax than ColdFusion regular expressions. For information on JavaScript regular expressions, see Input Validation with cfform Controls, in Chapter 9. For detailed descriptions of the ColdFusion functions that use regular expressions, see the CFML Reference.
Contents
About Regular Expressions ..................................................................................... 260 Basic Regular Expression Rules.............................................................................. 261 Multicharacter Regular Expressions ...................................................................... 263 Using Backreferences.............................................................................................. 265 Returning Matched Subexpressions ...................................................................... 266 Regular Expression Examples ................................................................................ 267
260
You often process large amounts of dynamic textual data. Regular expressions can be invaluable in writing complex ColdFusion applications. You can use the case-insensitive functions, REFindNoCase and REReplaceNoCase, for expressions where the search string is likely to be mixed case.
261
Character classes
In ColdFusion regular expressions, you can specify a character using one of the POSIX character classes. You enclose the character class name inside two square brackets, as in this example:
REReplace (Macromedia Web Site,[[:space:]],*,ALL)
262
This code replaces all the spaces with *, producing this string:
Macromedia*Web*Site
The following table shows the POSIX character classes that ColdFusion supports: Character Class alpha upper lower digit alnum xdigit space print punct graph cntrl Matches Matches any letter. Same as [A-Za-z]. Matches any uppercase letter. Same as [A-Z]. Matches any lowercase letter. Same as [a-z]. Matches any digit. Same as [0-9]. Matches any alphanumeric character. Same as [A-Za-z0-9]. Matches any hexadecimal digit. Same as [0-9A-Fa-f]. Matches a tab, new line, vertical tab, form feed, carriage return, or space. Matches any printable character. Matches any punctuation character, that is, one of ! # S % & ` ( ) *+,-./:;<=>?@[/]^_{|}~ Matches any of the characters defined as a printable character except those defined as part of the space character class. Matches any character not part of the character classes [:upper:], [:lower:], [:alpha:], [:digit:], [:punct:], [:graph:], [:print:], or [:xdigit:].
263
Here the regular expression [T]* can match empty strings. It first matches the empty string before H in Hello. Next, (note that the ALL artgument tells REReplace to replace all instances of an expression), the empty string before e is matched and so on until the empty string before o is matched. This result might be unexpected. The workarounds for these types of problems are specific to each case. In some cases you can use [T]+, which requires at least one T, instead of [T]*. Alternatively, you might be able to specify an additional pattern after [T]*. In the following example the regular expression has a W at the end:
<cfoutput>REReplace("Hello World","[T]*W","7","ALL") #REReplace("Hello World","[T]*W","7","ALL")#<BR></cfoutput>
A one-character regular expression or grouped subexpression followed by a question mark (?) matches zero or one occurrences of the regular expression; for example, xy?z matches either xyz or xz. The concatenation of regular expressions creates a regular expression that matches the corresponding concatenation of strings; for example, [A-Z][a-z]* matches any capitalized word. The OR character (|) allows a choice between two regular expressions; for example, jell(y|ies) matches either jelly or jellies. The following suffixes match repetitions of a regular expresion: {m,n}, where m is 0 or greater and n is greater than or equal to m, forces a match of m through n (inclusive) occurrences of the preceding regular expression; for example, (ba){2,4} matches baba, bababa, and babababa, but not ba or babababababa. {m,} forces a match of at least m occurrences of the preceding regular expression. The syntax {,n} is not allowed.
264
An excellent reference on regular expressions is Mastering Regular Expressions, Jeffrey E. F. Friedl. OReilly & Associates, Inc., 1997. ISBN: 1-56592-257-3, http:// www.oreilly.com.
Using Backreferences
265
Using Backreferences
ColdFusion Server supports backreferencing, which allows you to match text in previously matched sets of parentheses. A slash followed by a digit n (\n) refers to the nth subexpression in parentheses. One use for backreferencing is in searching for doubled words; for example, to find instances of the the or is is in text. The following example shows the syntax for backreferencing in regular expressions in ColdFusion:
REReplace("There is is coffee in the the kitchen", "([A-Za-z]+)[ ]+\1","*","ALL")
This code searches for words that are all letters ([A-Za-z]+) followed by one or more spaces [ ]+ followed by the first matched subexpression in parentheses. The parser detects the two occurrences of is as well as the two occurrences of the and replaces them with an asterisk, resulting in the following text:
There * coffee in * kitchen
You can use the optional fourth parameter in REReplace, scope, to replace all repeated words, as in the following code:
REReplace("There is is a cat in in the kitchen", "([A-Za-z]+)[ ]+\1","\1","ALL")
Note To use backreferences in either the search string or the replace string, you must use parentheses around the subexpression. Otherwise, ColdFusion throws an exception.
266
When ColdFusion executes the ReFind function, subExprs.pos[1]=7, subExprs.len[1]=5, subExprs.pos[2]=7, and subExprs.len[2]=2. The entries subExprs.pos[1] and subExprs.len[1] refer to the entire matched expression (is is), while subExprs.pos[2] and subExprs.len[2] refer to the first parenthesized subexpression (is). Because REFind returns information on the first regular expression match only, the subExprs structure does not contain information about the second match to the regular expression, "in in". For a full discussion of subexpression usage, see the sections on REFind and REFindNoCase in the ColdFusion Functions chapter of the CFML Reference.
267
Description A URL parameter value in a URL. An uppercase DOS/Windows full path that (a) is not the root of a drive, and (b) has only letters, numbers, and underscores in its text. A ColdFusion variable with no qualifier.
[A-Za-z][A-Za-z0-9_]*
([A-Za-z][A-Za-z0-9_]*)(\.[A-Za-z][A-Za- A ColdFusion variable with no more z0-9_]*)? than one qualifier; for example,
An integer that does not begin with a zero and has an optional sign. A real number. A real number in engineering notation. Two to four occurrences of a: aa, aaa, aaaa. At least three ba pairs: bababa, babababa, and so on..
Returns The query string with parameter CFID and its numeric value stripped out. I Lxxx Jxxxxxx
The string value of the variable Report with all positive numbers in the dollar format changed to "$***.**".
268
Expression
REFind ("[Uu]\.?[Ss]\.?[Aa}\.?", Report )
Returns The position in the variable Report of the first occurrence of the abbreviation USA. The letters can be in either case and the abbreviation can have a period after any letter. 4 There * coffee in * kitchen
REFindNoCase("a+c","ABCAACCDD") REReplace("There is is coffee in the the kitchen","([A-Za-z]+) [ ]+\1","*","ALL") REReplace(report, "<[^>]*>", "", "All")
Removes all HTML tags from a string value of the report variable.
Chapter 15
You can provide a full-text search capability for documents and data sources on a ColdFusion site by enabling the Verity search engine. ColdFusion 5 supports two Verity search engines: the default Verity search engine (VDK mode) and a restricted version of the Verity K2 Server. The ColdFusion installation and administration documentation provides information about using both engines. ColdFusion CFML tags for the two engines are identical except for how you specify the collection and external tag attributes. This chapter provides and overview of how use the Verity search engines to index and search data for your application.
Contents
Searching a ColdFusion Web Site........................................................................... 270 Supported File Types............................................................................................... 271 Support for International Languages .................................................................... 272 Creating a Searchable Data Source ........................................................................ 273 Indexing Query Results........................................................................................... 282 Using Query Expressions ........................................................................................ 285 Managing Collections ............................................................................................. 298
270
271
Word Processing
Applix Words (v4.2, 4.3, 4.4) HTML (Verity Zone Filter) Lotus AmiPro (v2.3) Lotus Ami Professional Write Plus Lotus Word Pro (v96, 97) Microsoft RTF Microsoft Word (v2, 6, 95, 97, 2000) Microsoft Word Mac (v4, 5, 6) Microsoft Word PC (v4.,5, 6) Microsoft Works Microsoft Write PDF (Verity PDF Filter) Text files (Verity Text Filter) Unicode WordPerfect (v5.x, 6, 7, 8) WordPerfect Mac (v2, 3) XyWrite (v4.12)
Spreadsheets
Applix Spreadsheets (v4.3, 4.4) Corel QuattroPro (v7, 8) Lotus 1-2-3 (v2, 3, 4, 5, 96, 97) Microsoft Excel (v3, 4, 5, 96, 97, 2000) Microsoft Works spreadsheet
Presentation Graphics
Corel Presentations (v.7.0, 8.0) Lotus Freelance (v.96, 97) Microsoft PowerPoint (v4.0, 95, 97, 2000)
272
273
You can use the Verity Wizard in ColdFusion Studio to create ColdFusion pages that index and search a collection. (The wizard does not create a page for creating the collection.) To run the wizard, select File > New and select the Verity Wizard from the CFML tab in the New Document dialog box.
Creating a Collection
The Verity engine performs searches against collections. A collection is a special database created by Verity that contains pointers to the indexed data that you specify for that collection. ColdFusions Verity implementation supports collections of three basic data types: Text files such as HTML pages and CFML pages Binary documents (see Supported File Types on page 271) Result sets returned from cfquery, cfldap, and cfpop queries You can build a collection from individual documents or from an entire directory tree. Collections can be stored anywhere, so you have a great deal of flexibility in accessing indexed data. You can use either of the following methods to create a Verity collection: Make selections on the ColdFusion Administrator Verity Collections page Code the cfcollection tag
To create a collection:
1 Open the ColdFusion Administrator Verity Collections page.
274
If you checked the option to install the ColdFusion documentation, the documentation collection is listed by default. The Verity engine is used to search the online documents. 2 3 In the top section of the page, enter a name for the collection. Enter a path for the directory location of the new collection. By default, new collections are added to \Cfusion\Verity\Collections\ in Windows and /opt/coldfusion/verity/collections in UNIX. 4 5 6 If you have an International Language Search Pack installed, you can select a language other than English for the collection from the drop-down list. Make sure Create a new collection is selected. Click Submit Changes. When the collection is created, the name and full path of the new collection appear in the Verity Collections list at the top of the page.
275
Note that this file simply shows how the form variables are used and does not perform error checking.
276
<cfcase value="Create"> <cfcollection action="Create" collection="#Form.CollectionName#" path="C:\CFUSION\Verity\Collections\"> <p>The collection #Form.CollectionName# is created. </cfcase> <cfcase value="Repair"> <cfcollection action="Repair" collection="#Form.CollectionName#"> <p>The collection #Form.CollectionName# is repaired. </cfcase> <cfcase value="Optimize"> <cfcollection action="Optimize" collection="#Form.CollectionName#"> <p>The collection #Form.CollectionName# is optimized. </cfcase> <cfcase value="Delete"> <cfcollection action="Delete" collection="#Form.CollectionName#"> <p>Collection deleted. </cfcase> </cfswitch> </cfoutput> </body> </html>
3 4
Save the file as collectioncreateaction.cfm. View the file collectioncreateform.cfm in your browser, enter values and submit the form.
Note
You can index and search against Verity collections created outside of ColdFusion by using the external attribute of cfindex and cfsearch.
277
7 8
278
Using cfindex
You can use a form page an action page similar to the following examples to select a collection and index it.
279
<cfoutput> The collection #Form.IndexColl# has been indexed. </cfoutput> </body> </html>
3 4
Save the file as collectionindexaction.cfm. View collectionindexform.cfm in your browser, enter values, and then click Index.
280
value=simple checked> Simple<br> <input type=radio name=type value=explicit> Explicit<br> <p>Enter a search string:</p> <input type=text name=searchstring size=50> <p><input type=submit name=search1 value="Search"> <input type=reset value="Reset"> </form> </body> </html>
Note
To use cfsearch to search a Verity K2 Server collection, the collection attribute must be the collections unique alias name as defined in the k2server.ini and the external attribute must be "No" (the default).
281
3 4
Save the file as collectionsearchaction.cfm. View the file collectionsearchform.cfm in your browser, enter values in the form, and then submit it.
Creating summaries
As part of the indexing process, Verity automatically produces a summary of every document file or every query result set that gets indexed. The default summarization selects the best sentences, based on internal rules, up to a maximum of 500 characters. Summarization information is returned by default with every cfsearch operation. For more information on this topic, see the Knowledge Base article Verity Custom1, Custom2 and Summary Fields (ID# 1081) at http://www.coldfusion.com/Support/KnowledgeBase/SearchForm.cfm. The cfsearch tag returns the summary for each found document in the query variable search_query.Summary. For example, to add a summary for each search result returned by the collectionsearchaction.cfm page, change the cfoutput query tag as follows:
<cfoutput query="Search1"> <a href="#Search1.URL#">#Search1.title#</a><br> #Summary#<br> </cfoutput>
For information on an advanced summarization technique, see the Knowledge Base article Verity: Synchronizing information stored in Verity Collection (ID# 1116) at http://www.coldfusion.com/Support/KnowledgeBase/SearchForm.cfm.
cfsearch properties
Each cfsearch query object includes three variables that provide information about the query: RecordCount The total number of records returned by the query. CurrentRow The current row of the query being processed by cfoutput. RecordsSearched The total number of records in the index that were searched. If no records were returned in the search, this property returns a null value.
282
To populate a collection from a cfquery you specify a key attribute, which corresponds to the primary key of the data source table, and a body attribute, the column or columns that you want to search for the index. The following extract shows only the cfquery and cfindex parts of the process.
<!--- Select the entire table ---> <cfquery name="Messages" datasource="MyMail"> SELECT * FROM Messages </cfquery> <!--- Output the result set ---> <cfoutput query="Messages"> #Message_ID#, #Subject#, #Title#, #MessageText# </cfoutput> <!--- Index the result set ---> <cfindex collection="DBIndex" action="Update" type="Custom"
283
This cfindex statement specifies the MessageText column as the information to be indexed and names the tables primary key, the Message_ID column, as the key value. Note that the title attribute names the Subject column. You can use the title attribute to designate an output parameter. To index more than one column in a collection, enter a comma-separated list of column names for values of the body attribute, such as:
body=FirstName,LastName,Company
284
<cfindex action="update" collection="ldap_query" key="dn" type="custom" title="o" query="OrgList" body="telephonenumber"> <!--- Search the collection ---> <!--- Use the wildcard * to contain the search string ---> <cfsearch collection="ldap_query" name="s_ldap" criteria="*617*"> <!--- Output returned records ---> <cfoutput query="s_ldap"> #Key#, #Title#, #Body# <br> </cfoutput>
285
type="custom" title="subject" query="p_messages" body="body"> <!--- Search messages for the word "action" ---> <cfsearch collection="pop_query" name="s_messages" criteria="action"> <!--- Output search result set ---> <cfoutput query="s_messages"> #key#, #title# <br> </cfoutput>
286
A simple query automatically employs the STEM operator and the MANY modifier. STEM searches for words that derive from those entered in the query expression, so entering find returns documents that contain find, finding, finds, and so on. The MANY modifier presents the documents returned in the search as a list based on a relevancy score.
Expression syntax
You can use either simple or explicit syntax when stating simple query syntax. The syntax you use determines whether the search words you enter are stemmed, and whether the words that are found contribute to relevance-ranked scoring.
Simple syntax
When you use simple syntax, the search engine implicitly interprets single words as if they were modified by the MANY and STEM operators. By implicitly applying the MANY operator, the search engine calculates each documents score based on the density of the search term in the searched documents. The more frequent is the occurrence of a word in a document, the higher is the documents score. As a result, the search engine ranks documents according to word density as it searches for the word you specify, as well as words that have the same stem. For example, films, filmed, and filming are stemmed variations of the word film. To search for documents containing the word film and its stem words, you can enter the word film without modification. When documents are ranked by relevance, they appear in a list with the most relevant documents at the top.
Explicit syntax
When you use explicit syntax, the search engine interprets the search terms you enter as literals. For example, by entering the word film (including quotation marks) using explicit syntax, the stemmed versions of the word film, films, filmed, and filming are ignored. The following table shows all operators available for conducting searches of ColdFusion Verity collections. Verity Search Operators < <= CONTAINS ENDS PHRASE SENTENCE
287
Verity Search Operators = > >= Accrue AND MATCHES NEAR NEAR/N OR PARAGRAPH STARTS STEM SUBSTRING WILDCARD WORD
Special characters
The search engine handles a number of characters in particular ways as described in the following table: Characters ,()[ =><! @ <{[! Description These characters end a text token. These characters also end a text token. They are terminated by an associated end character. These characters signify the start of a delimited token. They are terminated by an associated end character.
A backslash (\) removes special meaning from whatever character follows it. To enter a literal backslash in a query, use two in succession; for example:
<FREETEXT>("\"Hello\", said Packard.") "backslash (\\)"
Precedence rules
Expressions are read from left to right. The AND operator takes precedence over the OR operator. However, terms enclosed in parentheses are evaluated first. When the search engine encounters nested parentheses, it starts with the innermost term.
288
When you use prefix notation, the expression specifies precedence explicitly. The following example means: Look for documents that contain b and c first, then documents that contain a:
OR (a, AND (b,c))
When you use infix notation, precedence is implicit in the expression. For example, the AND operator takes precedence over the OR operator.
Commas in expressions
If an expression includes two or more search terms within parentheses, a comma is required as a separator between the elements. The following example means: Look for documents that contain any combination of a and b together.
<OR> (a, b)
Note that in this example, angle brackets are used with the OR operator.
Delimiters in expressions
You use angle brackets (< >), double quotation marks ("), and backslashes (\) to delimit various elements in a query expression, as described in the following table: Angle brackets Left and right angle brackets are reserved for designating operators and modifiers. They are optional for the AND, OR, and NOT operators, but required for all other operators.
Double quotation You use double quotation marks in expressions to search for a marks word that is otherwise reserved as an operator, such as AND, OR, and NOT. Backslashes To include a backslash in a search expression, insert two backslashes for each backslash character you want included in the search; for example, C:\\CFUSION\\BIN.
[]
289
Wildcard {}
Description Curly braces. Matches any one of a set of patterns separated by a comma, as in hoist{s, ing, ed}, which locates hoists, hoisting, and hoisted. Caret. Matches any character not in the set, as in sl[^ia]m, which locates slum but not slim or slam. Hyphen. Specifies a range of characters in a set, as in c[a-r]t, which locates every word beginning with c, ending with t, and containing any letter from a to r.
^ -
290
Operators
An operator represents logic to be applied to a search element. This logic defines the qualifications that a document must meet to be retrieved. You can use operators to refine your search or to influence the results in other ways. For example, you could construct an HTML form for conducting searches. In the form, a user could perform a search for a single term: server. You can refine your search by limiting the search scope in a number of ways. Operators are available for limiting a query to a sentence or paragraph, and you can search words based on proximity. Ordinarily, you use operators in explicit searches, as shown here:
"<operator>search_string"
The following operator types are available: Operator type Evidence Proximity Relational Concept Score Natural language Purpose Specifies basic and intelligent word searches. Specifies the relative location of words in a document. Searches fields in a collection. Identifies a concept in a document by combining the meanings of search elements. Manipulates the score returned by a search element. You can set the score percentage display to as many as four decimal places. Allows the use of natural language expressions in forming queries.
Evidence operators
Evidence operators let you specify a basic word search or an intelligent word search. A basic word search finds documents that contain only the word or words specified in the query. An intelligent word search expands the query terms to create an expanded word list so that the search returns documents that contain variations of the query terms. Documents retrieved using evidence operators are not ranked by relevance unless you use the MANY modifier.
291
The following tale describes the evidence operators: Operator STEM Description Expands the search to include the word you enter and its variations. The STEM operator is automatically implied in any simple query. For example, the explicit query expression:
<STEM>believe
yields matches such as believe, believing, and believer. WILDCARD Matches wildcard characters included in search strings. Certain characters automatically indicate a wildcard specification, such as apostrophe (*) and question mark(?). For example, the query expression:
spam*
yields matches such as, spam, spammer, and spamming. WORD Performs a basic word search, selecting documents that include one or more instances of the specific word you enter. The WORD operator is automatically implied in any SIMPLE query. Expands the search to include the word you enter and its synonyms. Expands the search to include the word you enter and one or more words that sound like, or whose letter pattern is similar to, the word specified. Collections do not have sound-alike indexes by default; to use this feature you must build sound-alike indexes. Expands the search to include the word you enter plus words that are similar to the query term. This operator performs approximate pattern matching to identify similar words. The optional N variable in the operator name expresses the maximum number of errors between the query term and a matched term, a value called the error distance. If N is not specified, an error distance of 2 is used.
THESAURUS SOUNDEX
TYPO/N
Proximity operators
Proximity operators specify the relative location of specific words in the document. Specified words must be in the same phrase, paragraph, or sentence for a document to be retrieved. In the case of NEAR and NEAR/N operators, retrieved documents are ranked by relevance based on the proximity of the specified words. Proximity operators can be nested; phrases or words can appear within SENTENCE or PARAGRAPH operators, and SENTENCE operators can appear within PARAGRAPH operators.
292
The following table describes the proximity operators: Operator NEAR Description Selects documents containing specified search terms. The closer the search terms are to one another within a document, the higher the documents score. The document with the smallest possible region containing all search terms always receives the highest score. Documents whose search terms are not within 1000 words of each other are not selected. Selects documents containing two or more search terms within N number of words of each other, where N is an integer between 1 and 1024. NEAR/1 searches for two words that are next to each other. The closer the search terms are within a document, the higher the documents score. You can specify multiple search terms using multiple instances of NEAR/N as long as the value of N is the same:
commute <NEAR/10> bicycle <NEAR/10> train <NEAR/10>
NEAR/N
PARAGRAPH Selects documents that include all of the words you specify within the same paragraph. To search for three or more words or phrases in a paragraph, you must use the PARAGRAPH operator between each word or phrase. <PARAGRAPH> (mission, goal). PHRASE Selects documents that include a phrase you specify. A phrase is a grouping of two or more words that occur in a specific order. Examples:
mission oak mission oak mission <PHRASE> oak
SENTENCE
Selects documents that include all of the words you specify within the same sentence. Examples:
jazz <SENTENCE> musician <SENTENCE> (jazz, musician)
IN
Selects documents that contain specified values in one or more document zones. A document zone represents a region of a document, such as the documents summary, date, or body text. The IN operator can be qualified with the WHEN operator, to search for a term only within the one or more zones upon which certain conditions have been placed.
Relational operators
Relational operators search document fields that you defined in the collection. Documents containing specified field values are returned. Documents retrieved using relational operators are not ranked by relevance, and you cannot use the MANY modifier with relational operators.
293
You use the following operators for numeric and date comparisons: Operator = > >= < <= Description Equals Greater than Greater than or equal to Less than Less than or equal to
The following relational operators compare text and match words and parts of words: Operator CONTAINS Description Selects documents by matching the word or phrase you specify with the values stored in a specific document field. Documents are selected only if the search elements specified appear in the same sequential and contiguous order in the field value; for example, god matches God in heaven, a god among men, or good god but not godliness, or gods. Selects documents by matching the query string with values stored in a specific document field. Documents are selected only if the search elements specified match the field value exactly. If a partial match is found, a document is not selected; for example, god matches a document field containing only god and does not match gods, godliness, or a god among men. Selects documents by matching the character string you specify with the starting characters of the values stored in a specific document field. Selects documents by matching the character string you specify with the ending characters of the values stored in a specific document field. Selects documents by matching the query string you specify with any portion of the strings in a specific document field; for example, god matches godliness, a god among men, godforsaken, and so on.
MATCHES
STARTS
ENDS
SUBSTRING
294
Document fields
You can specify the values for the cfindex attributes TITLE, KEY, URL, and CUSTOM as document fields for use with relational operators in the criteria attribute. Document fields are referenced in text comparison operators. They are identified as: CF_TITLE CF_KEY CF_URL CF_CUSTOM1 CF_CUSTOM2 For more information on this topic, see the Knowledge Base article, Verity: Using Document Fields To Narrow Down Searches (ID# 1082) on our Web site at http:// www.coldfusion.com/Support/KnowledgeBase/SearchForm.cfm.
The following application page matches records that have 1990 in the TEXT column and are in the Place Utah. The search is performed against the collection that contains the TEXT column and then is narrowed further by searching for the string Utah in the CF_TITLE document field. Recall that document fields are defaults defined in every collection corresponding to the values you define for URL, TITLE, and KEY in the cfindex tag.
<cfquery name="GetText" datasource="TEST1"> SELECT Year+Place AS Identifier, text FROM YearPlaceText </cfquery> <cfindex collection="testcollection" action="Update" type="Custom" title="Identifier"
295
key="Identifier" body="TEXT" query="GetText"> <cfsearch name="GetText_Search" collection="testcollection" type="Explicit" criteria="1990 and CF_TITLE <SUBSTRING> Utah"> <cfoutput> Record Counts: <br> #GetText.RecordCount# <br> #GetText_Search.RecordCount# <br> </cfoutput> Query Results --- Should be 5 rows <br> <cfoutput query="Gettext"> #Identifier# <br> </cfoutput> Search Results -- should be 1 row <br> <cfoutput query="GetText_Search"> #GetText_Search.TITLE# <br> </cfoutput>
Concept operators
Concept operators combine the meaning of search elements to identify a concept in a document. Documents retrieved using concept operators are ranked by relevance. The following table describes each concept operator: Operator AND OR ACCRUE Description Selects documents that contain all the search elements you specify. Selects documents that show evidence of at least one of the search elements you specify. Selects documents that include at least one of the search elements you specify. Documents are ranked based on the number of search elements found. Selects documents that contain all of the search elements you specify. A score of 1.00 is assigned to each retrieved document. ALL and AND retrieve the same results, but queries using ALL are always assigned a score of 1.00. Selects documents that contain at least one of the search elements you specify. A score of 1.00 is assigned to each retrieved document. ANY and OR retrieve the same results, but queries using ANY are always assigned a score of 1.00.
ALL
ANY
296
Score operators
Score operators govern how the search engine calculates scores for retrieved documents. The maximum score that a returned search element can have is 1.000. You can set the score percentage display to as many as four decimal places. When you use a score operator, the search engine first calculates a separate score for each search element found in a document, and then performs a mathematical operation on the individual element scores to arrive at the final score for each document. Note that the documents score is available as a result column. You can use the SCORE result column to get the relevancy score of any document retrieved. For example:
<cfoutput> <a href="#Search1.URL#">#Search1.Title#</a><br> Document Score=#Search1.SCORE#<BR> </cfoutput>
The following table describes the score operators: Operator YESNO Description Forces the score of an element to 1 if the elements score is non-zero:
<YESNO>mainframe
If the retrieval result of the search on mainframe is 0.75, the YESNO operator forces the result to 1. You can use YESNO to avoid relevance ranking. PRODUCT Multiplies the scores for the search elements in each document matching a query:
<PRODUCT>(computers, laptops)
Takes the product of the resulting scores. SUM Adds together the scores for the search element in each document matching a query, up to a maximum value of 1:
<SUM>(computers, laptops)
Takes the sum of the resulting scores. COMPLEMENT Calculates scores for documents matching a query by taking the complement (subtracting from 1) of the scores for the query's search elements. The new score is 1 minus the search element's original score.
<COMPLEMENT>computers
If the search element's original score is .785, the COMPLEMENT operator recalculates the score as .215.
297
Modifiers
You combine modifiers with operators to change the standard behavior of an operator in some way. For example, you can use the CASE modifier with an operator to specify that you want to match the case of the search word. The following table describes the available modifiers. Modifier CASE Description Specifies a case-sensitive search. Normally, Verity searches are case-insensitive for search text entered in all uppercase or all lowercase, and case-sensitive for mixed-case search strings. The expression:
<CASE>J[JAVA, java]
Searches for JAVA and Java. MANY Counts the density of words, stemmed variations, or phrases in a document and produces a relevance-ranked score for retrieved documents. Use with the following operators: WORD WILDCARD STEM PHRASE SENTENCE PARAGRAPH Here is an example:
<PARAGRAPH><MANY>javascript <AND> vbscript
You cannot use the MANY modifier with the following: AND OR ACCRUE Relational operators NOT Use to exclude documents that contain the specified word or phrase. Use only with the AND and OR operators. Here is an example:
Java <AND> programming <NOT> coffee
ORDER
Use to specify that the search elements must occur in the same order in which they are specified in the query. Use with the following operators: PARAGRAPH SENTENCE NEAR/N Place the ORDER modifier before any operator, as follows:
<ORDER><PARAGRAPH>("server", "Java")
298
Managing Collections
As with any data source, the maintenance requirements of a Verity collection are dictated by the number, frequency, and type of changes that occur in the records. You can run maintenance routines directly from either the cfcollection or cfindex tags or via the Administrator Verity Collections page. For more information on this topic, see the Knowledge Base article Maintaining Collections (ID# 1080) at http:// www.coldfusion.com/Support/KnowledgeBase/SearchForm.cfm. The easiest way to perform collection management tasks is to create a ColdFusion page that runs the operations, and then add the task on the Administrator Scheduler page. The page presents a wide range of scheduling options.
Maintenance options
Choose an option based on the following function descriptions: Repair Runs internal Verity routines to fix corrupted records. If you suspect a collection is corrupted, it is probably safest to repopulate it. Optimize Packs the indexed data for better performance. You can use this procedure, which is similar to database optimization, as part of routine maintenance. You should not use the Optimize action in a cfindex tag except to maintain legacy code. The cfcollection tag is recommended instead. For more information on this command, see the Knowledge Base article How To Optimize Your Verity Collection (ID# 416) at http://www.coldfusion.com/Support/ KnowledgeBase/SearchForm.cfm. Purge Removes all data marked for deletion from a collection. Delete as the cfindex action attribute Marks for deletion the specified key attribute value, or comma-separated values, from the collection. Use Purge to remove these items. Delete on the Administrator Verity Collections page or in cfcollection Deletes the entire collection. Update Repopulates the collection with changed records and new records and adds a key if one is not part of the collection. This operation does not delete records that have been deleted from the data source. To update a collection from the Administrator Verity main page, select a collection on the list, click Index, and then click Update on the index page. Refresh (cfindex action attribute only) Deletes all data and repopulates the collection.
Securing a collection
Scenarios for restricting access to a Verity collection include: The ColdFusion Administrator might need to specify developer access to collections. A public site might need to limit user access to collections.
Managing Collections
299
You can then develop an appropriate authentication interface to allow access to the secured collection.
300
Chapter 16
You can add interactive mail features to your ColdFusion applications, providing a complete two-way interface to mail servers via the cfmail tag and the cfpop tag. The boom in Internet mail services makes ColdFusions enhanced e-mail capability a vital link to your users.
Contents
Using ColdFusion with Mail Servers...................................................................... 302 Sending E-mail Messages ....................................................................................... 302 Sample Uses of cfmail ............................................................................................. 304 Customizing E-mail for Multiple Recipients......................................................... 306 Advanced Sending Options .................................................................................... 308 Receiving E-mail Messages..................................................................................... 309 Handling POP Mail.................................................................................................. 310
302
The page displays a message indicating success or failure at connecting to the server. For more information on the Administrators mail settings, see Advanced ColdFusion Administration.
303
3 4
Save the file as sendmail.cfm in myapps under the Web root directory. Open your browser and enter the URL that contains the file; for example:
http://localhost/myapps/[email protected]
(Replace [email protected] with your e-mail address.) The page sends the e-mail to you, through your SMTP server.
304
305
#ProductRequests.FirstName# #ProductRequests.LastName# (#ProductRequests.Company#) #ProductRequests.EMailAddress#&##013; </cfoutput> Regards, The WebMaster [email protected] </cfmail>
Note the use of the cfoutput tag to present a dynamic list embedded within a normal cfmail message. The text within the cfoutput is repeated for each row in the ProductRequests query, while the text above and below it serve as the header and footer, respectively, for the mail message. The &##013; in the cfoutput block forces a carriage return between output records.
Note that in this example, the contents of the cfmail tag body are not dynamic, that is, the tag does not use any # delimited dynamic parameters. What is dynamic is the list of e-mail addresses to which the message is sent. Note the use of the TesterEMail column from the BetaTesters query in the to attribute.
306
Note that in the to attribute of cfmail, the #Email# query column causes one message to be sent to the address listed in each row of the query, and that the mail body therefore does not use a cfoutput tag. Also note the use of the other query columns (FirstName, LastName, and so on) within the cfmail section to customize the contents of the message for each recipient.
307
308
309
Using cfpop
Use the followig steps to add POP mail to your application
310
311
<h2>This example retrieves message header information:</h2> <cfpop server="mail.company.com" username=#myusername# password=#mypassword# action="GetHeaderOnly" name="Sample"> <cfoutput query="Sample"> MessageNumber: #HTMLEditFormat(Sample.messageNumber)# <br> To: #HTMLEditFormat(Sample.to)# <br> From: #HTMLEditFormat(Sample.from)# <br> Subject: #HTMLEditFormat(Sample.subject)# <br> Date: #HTMLEditFormat(Sample.date)#<br> Cc: #HTMLEditFormat(Sample.cc)# <br> ReplyTo: #HTMLEditFormat(Sample.replyTo)# <br><br> </cfoutput> </body> </html>
Change the following line so that it refers to a valid POP mail server, as well as a valid user name and password:
<cfpop server="mail.company.com" username=#username# password=#password#
Save the file as hdronly.cfm in myapps under the Web root directory and view it in the ColdFusion Studio Browse tab or your Web browser.
This code retrieves the message headers and stores them in a cfpop query result set called Sample. The ColdFusion function HTMLEditFormat replaces characters that have meaning to HTML, such as the < and > signs that can surround detailed e-mail address information, with escaped characters such as < and >. In addition, you can process the date returned by cfpop with ParseDateTime, which accepts an argument for converting POP date/time objects into a CFML date-time object. For information on these ColdFusion functions, see the CFML Reference. You can reference any of these columns in a cfoutput tag, as the following example shows.
<cfoutput> #ParseDateTime(queryname.date, "POP")# #HTMLCodeFormat(queryname.from)# #HTMLCodeFormat(queryname.messageNumber)# </cfoutput>
312
Change the following line so that it refers to a valid POP mail server, as well as to a valid user name and password:
<cfpop server="mail.company.com" username=#username# password=#password#
Save the file as hdrbody.cfm in myapps under the Web root directory and view it in the ColdFusion Studio Browse tab or your Web browser.
313
Note that this example does not use a CFML function to encode the body contents. As a result, the browser displays the formatted message as you would normally see it in a mail program that supports HTML messages.
314
<br> Body:<br> #Sample.body# <br> <br> Header:<br> HTMLCodeFormat(Sample.header)# <br> <hr> </cfoutput> </body> </html>
Change the following line so that it refers to a valid POP mail server, as well as to a valid user name and password:
<cfpop server="mail.company.com" username=#username# password=#password#
Save the file as hdrbody.cfm in myapps under the Web root directory and view it in the ColdFusion Studio Browse tab or your Web browser.
Note To avoid duplicate filenames when saving attachments, set the generateUniqueFilenames attribute of cfpop to Yes.
Deleting messages
By default, retrieved messages are not deleted from the POP mail server. If you want to delete retrieved messages, you must set the action attribute to Delete. You must also specify use the messagenumber attribute to specify the numbers of the messages to delete. Using cfpop to delete a message permanently removes it from the server. If the messagenumber does not correspond to a message on the server, ColdFusion generates an error. Note Message numbers are reassigned at the end of every POP mail server communication that contains a delete action. For example, if you retrieve four messages from a POP mail server, the message numbers returned are 1,2,3,4. If you then delete messages 1 and 2 with a single cfpop tag, messages 3 and 4 are assigned message numbers 1 and 2, respectively.
315
To delete messages:
1 2 Create a new file in ColdFusion Studio. Modify the file so that it appears as follows:
<html> <head> <title>POP Mail Message Delete Example</title> </head> <body> <h2>This example deletes messages:</h2> <cfpop server="mail.company.com" username=#username# password=#password# action="Delete" messagenumber="1,2,3"> </body> </html>
Change the following line so that it refers to a valid POP mail server, as well as to a valid user name and password:
<cfpop server="mail.company.com" username=#username# password=#password#
Save the file as hdrbody.cfm in myapps under the Web root directory. Caution When you view this page in your browser or the ColdFusion Studio Browse tab, it immediately deletes the messages from your POP server.
316
Chapter 17
The cffile, cfdirectory, and cfcontent tags handle browser/server file management tasks. To perform server-to-server operations, use the CFFTP tag, described in Performing File Operations with cfftp on page 341.
Contents
Using cffile ............................................................................................................... 318 Uploading Files........................................................................................................ 319 Setting File and Directory Attributes ..................................................................... 323 Evaluating the Results of a File Upload ................................................................. 324 Moving, Renaming, Copying, and Deleting Server Files ...................................... 326 Reading, Writing, and Appending to a Text File.................................................... 327 Performing Directory Operations .......................................................................... 329
318
Using cffile
The cffile tag gives you the ability to work with files on your server in a number of ways: Uploading files from a client to the Web server using an HTML form Moving, renaming, copying, or deleting files on the server Reading, writing, or appending to text files on the server You use the action attribute to specify any of the following file actions: upload, move, rename, copy, delete, read, readBinary, write, and append. The required attributes depend on the action specified. For example, if action="write", ColdFusion expects the attributes associated with writing a text file.
Note
Consider the security and logical structure of directories on the server before allowing users access to them. You can disable the cffile tag on the Tag Restrictions page of the ColdFusion Administrator Security tab. Also, to access files that are not located on the local ColdFusion Server system, ColdFusion services must run using an account with permission to access the remote files and directories.
Uploading Files
319
Uploading Files
File uploading requires that you create two files: An HTML form to enter file upload information An action page containing the file upload code
Save the file as uploadfileform.cfm in myapps under the Web root directory.
Description Create a form that contains file selection fields for upload by the user. The enctype attribute value tells the server that the form submission contains an uploaded file Allow the user to input a field. The file type instructs the browser to prepare to read and transmit a file from the users system to your server and automatically includes a Browse button to allow the user to look for the file instead of entering the entire path and filename.
320
The user can enter a file path or browse the system and pick a file to send.
<cfoutput> You uploaded the file #cffile.ClientFileName#.#cffile.ClientFileExt# successfully to #cffile.ServerDirectory#\#cffile.ServerFileName#.#cffile. ServerFileExt#. </cfoutput> </body> </html>
3 4 5
Save the file as uploadfileaction.cfm in myapps under the Web root directory. View uploadfileform.cfm in your browser, enter values and submit the form. The file you specified is uploaded.
Uploading Files
321
Description Prepare to upload a file to the server. Specify the destination of the file. If the file already exists, overwrite it. Specify the name of the file to upload. Note that you do not enclose the variable in pound signs. Inform the user of the file that was uploaded and its destination. For information on cffile scope variables, see Evaluating the Results of a File Upload on page 324.
Note
This example performs no error checking and does not incorporate any security measures. Before deploying an application that performs file uploads, be sure to incorporate both error handling and security.
322
Note
Not all browsers support MIME type associations.
This cffile specification saves an image file only if it is in GIF or JPEG format:
<cffile action="Upload" fileField="Form.FiletoUpload" destination="c:\uploads\MyImage.GIF" nameConflict="Overwrite" accept="image/gif, image/jpeg">
This cffile specification saves any image file, regardless of the format:
<cffile action="Upload" fileField="Form.FiletoUpload" destination="c:\uploads\MyImage.GIF" nameConflict="Overwrite" accept="image/*">
Note
ColdFusion saves any uploaded file if you omit the accept attribute, leave it empty, or specify "*/*".
323
Windows
In Windows, you can set the following file attributes: ReadOnly Temporary Archive Hidden System Normal To specify several attributes, use a comma-separated list, such as attributes="ReadOnly,Archive". If you do not use attributes, the files existing attributes are maintained. If you specify any other attributes with Normal, the additional attribute overrides the Normal setting.
Note
Make sure you include the trailing slash (\) when you specify the destination directory. Otherwise, ColdFusion treats the last element in the pathname as a filename.
UNIX
In UNIX, you can set permissions on files and directories for owner, group, and other. Values for the mode attribute correspond to octal values for the UNIX chmod command: 4 = read 2 = write 1 = execute
324
You enter permissions values in the mode attribute for each type of user: owner, group, and other in that order. For example, use the following code to assign read permissions for everyone:
mode=444
To give a file or directory owner read/write/execute permissions and read only permissions for everyone else:
mode=744
MIME content type of the saved file, such as image for image/gif. Date that the uploaded file was last accessed. Indicates (Yes or No) whether the file already existed with the same path. Size of the uploaded file.
325
Variable fileWasAppended fileWasOverwritten fileWasRenamed fileWasSaved oldFileSize serverDirectory serveFile serverFileName serverFileExt timeCreated timeLastModified
Description Indicates (Yes or No) whether ColdFusion appended the uploaded file to an existing file. Indicates (Yes or No) whether ColdFusion overwrote a file. Indicates (Yes or No) whether the uploaded file was renamed to avoid a name conflict. Indicates (Yes or No) whether ColdFusion saved a file. Size of a file that was overwritten in the file upload operation. Empty if no file was overwritten. Directory where the file was saved on the server. Full name of the file saved on the server with the file extension; for example, myfile.txt. Name of the file saved on the server without an extension; for example, myfile. Extension of the file saved on the server without a period; for example, txt, not .txt. Date and time the uploaded file was created. Date and time of the last modification to the uploaded file.
Note
File status variables are read-only. They are set to the results of the most recent cffile operation. If two cffile tags execute, the results of the first are overwritten by the subsequent cffile operation.
326
Rename a file
<cffile action="Rename" source="c:\files\memo\KeyMemo.doc" destination="c:\files\memo\OldMemo.doc"> <cffile action="Copy" source="c:\files\upload\KeyMemo.doc" destination="c:\files\backup\"> <cffile action="Delete" file="c:\files\upload\oldfile.txt">
Copy a file
Delete a file
327
3 4
Replace C:\inetpub\wwwroot\mine\message.txt with the location and name of a text file on your server. Save the file as readtext.cfm and view it in your browser.
328
Save the file as writetextfileform.cfm in myapps under the Web root directory.
3 4 5
Modify the path C:\inetpub\wwwroot\mine\ to point to a path on your server. Save the file as writetextfileaction.cfm. View the file writetextfileform.cfm in your browser, enter values, and submit the form.
329
The text file is written to the location you specified. If the file already exists, it is replaced. You can use cffile action="Append" to append additional text to the end of an existing text file, for example, when you create log files.
330
<th>Modified</th> <th>Attributes</th> <th>Mode</th> </tr> <cfoutput query="mydirectory"> <tr> <td>#mydirectory.name#</td> <td>#mydirectory.size#</td> <td>#mydirectory.type#</td> <td>#mydirectory.dateLastModified#</td> <td>#mydirectory.attributes#</td> <td>#mydirectory.mode#</td> </tr> </cfoutput> </table> </body> </html>
3 4
Modify the line directory="c:\inetpub\wwwroot\mine"so that it points to a directory on your server. Save the file as directoryinfo.cfm and view it in your browser.
Note that depending on whether your server is on a UNIX system or a Windows system, either the Attributes column or the Mode column is empty. Also, you can specify a filename in the filter attribute to get information on a single file.
Chapter 18
This chapter describes how ColdFusion wraps the complexity of Hypertext Transfer Protocol (HTTP) and File Transfer Protocol (FTP) communications in a simplified tag syntax that lets you easily extend your sites offerings across the Web.
Contents
Using cfhttp to Interact with the Web.................................................................... 332 Using the cfhttp Get Method.................................................................................. 332 Creating a Query from a Text File........................................................................... 335 Using the cfhttp Post Method................................................................................. 337 Performing File Operations with cfftp................................................................... 341 Moving Complex Data Structures Across the Web with WDDX .......................... 345 Converting CFML Data to a JavaScript Object...................................................... 349 Transferring Data from Browser to Server............................................................. 350 Storing Complex Data in a String........................................................................... 353
332
3 4
(Optional) Replace the url attribute value with the URL of a file you want to get. Save the file as getwebpage.cfm in myapps under your Web root directory and view it in your browser.
333
Description Get the page specified in the URL and make the links absolute instead of relative so that they display properly. Display the page, which is stored in the variable cfhttp.fileContent, in the browser.
3 4 5
(Optional) Replace the url attribute value with the URL of a file you want to save and change the filename. (Optional) Change the path from C:\temp to a path on your hard drive. Save the file as savewebpage.cfm and view it in a text editor. The file does not display properly in your browser because the Get operation saves only the specified Web page. It does not save the frame, image, or other files that the page might include.
Description Get the page specified in the URL and save it in the file specified in path and file. When you use the path and file attributes, ColdFusion ignores any resolveurl attribute. As a result, frames and other included files cannot display when you view the saved page.
334
3 4 5
Change the URL to point to a binary file you want to download. Change the path to point to a path on your hard drive. Save the file as savebinary.cfm in myapps under your Web root directory and view it in your browser.
Description Get a binary file and save it in the path and file specified.
335
336
<!--- Now substitute different column names ---> <!--- by using the columns attribute ---> <hr> Now using replacement column names<br> <cfhttp method="Get" url="http://127.0.0.1/orders/june/orders.txt" name="juneorders" columns="ID,Number,ODate,SDate,Name,Address" delimiter=","> <cfoutput query="juneorders"> Order ID: #ID#<br> Order Number: #Number#<br> Order Date: #SDate#<br> </cfoutput>
3 4 5
Substitute the URL with the location of your text file. Substitute the name of a text file and the column headers to those in your text file. Save the file as querytextfile.cfm in myapps under your Web root directory and view it in your browser.
337
338
</body> </html>
3 4
Replace the path to the GIF file to a path on your server. Save the file as posttest.cfm in myapps under your Web root directory.
Description Post an HTTP request to the specified page. Send a cookie in the request.
Send a file in the request. The </cfhttp> tag ends the http request. Display the contents of the file that the page that is posted to creates by processing the request. In this example, this is the output from the cfoutput tag in server.cfm. Display the MIME type of the created file.
339
<cfoutput> The URL variable is: #URL.myurl# <br> The Cookie variable is: #Cookie.mycookie6# <br> The CGI variable is: #CGI.mycgi#. <br> The Formfield variable is: #Form.emailaddress#. <br> The file was uploaded to #File.ServerDirectory#\#File.ServerFile#. </cfoutput>
3 4 5
Replace C:\temp\Junk with an appropriate directory path on your hard drive. Save the file as server.cfm in myapps under your Web root directory. View posttest.cfm in your browser and look for the file in C:\temp\Junk (or your replacement path).
Description Write the transferred document to a file on the server. Note that you send the file using the cfhttpparam type="File" attribute, but the receiving page gets it as a Form variable, not a File variable. This cffile tag creates File variables, as follows. Output information. The results are not displayed by this page. They are passed back to the posting page in its cfhttp.filecontent variable. Output the value of the URL variable sent in the HTTP request. Output the value of the Cookie variable sent in the HTTP request. Output the value of the CGI variable sent in the HTTP request. Output the Form variable sent in the HTTP request. Note that you send the variable using the type="formField" attribute but the receiving page gets it as a Form variable. Output the results of the cffile tag on this page. This time, the variables really are File variables.
<cfoutput>
The Cookie variable is: #Cookie.mycookie# <br> The CGI variable is: #CGI.mycgi# <br>
340
341
Note
To use cfftp, the Enable cfftp Tag option must be selected on the Tag Restrictions page of the Basic Security section of the ColdFusion Administrator Security tab. For server/browser operations, use the cffile, cfcontent, and cfdirectory tags. Using cfftp involves two major types of operations: connecting, and transferring files. The FTP protocol also provides commands for listing directories and performing other operations. For a complete list of attributes that support FTP operations and additional details on using the cfftp tag, see the CFML Reference.
342
<!--- Close the connection.---> <cfftp action="close" connection="Myftp"> <p>Did the connection close successfully? <cfoutput>#cfftp.succeeded#</cfoutput></p> <!--- output dirlist results ---> <hr> <p>FTP Directory Listing:</p> <cftable query="dirlist" colheaders="yes" htmltable> <cfcol header="<B>Name</b>" TEXT="#name#"> <cfcol header="<B>Path</b>" TEXT="#path#"> <cfcol header="<B>URL</b>" TEXT="#url#"> <cfcol header="<B>Length</b>" TEXT="#length#"> <cfcol header="<B>LastModified</b>" TEXT="#DateFormat(lastmodified)#"> <cfcol header="<B>IsDirectory</b>" TEXT="#isdirectory#"> </cftable>
3 4
Change MyServer to the name of a server for which you have FTP permission. Change MyUserName and MyPassword to a valid username and password. To establish an anonymous connection, enter anonymous as the username and an e-mail address (by convention) for the password.
Save the file as ftpconnect.cfm in myapps under your Web root directory.
Description Open an FTP connection to the MyServer server and log on as MyUserName. If an error occurs, stop processing and display an error. You can use this connection in other cfftp tags by specifying the Myftp connection. Use the Myftp connection to get the name of the current directory; stop processing if an error occurs. Display the current directory.
343
Code
<cfftp connection=Myftp action="ListDir" directory="#cfftp.returnvalue#" name="dirlist" stoponerror="Yes">
Description Use the Myftp connection to get a directory listing. Use the value returned by the last cfftp call (the current directory of the connection) to specify the directory to list. Save the results in a variable named dirlist (a query object). Stop processing if there is an error. Close the connection, and do not stop processing if the operation fails (because you can still use the results). Instead, display the value of the cfftp.succeeded variable, which is Yes if the connection is closed, and No if the operation failed. Display a table with the results of the ListDir FTP command.
<cfftp action="close" connection="Myftp"> <p>Did the connection close successfully? <cfoutput>#cfftp.succeeded#</ cfoutput></p>
<cftable query="dirlist" colheaders="yes" htmltable> <cfcol header="<B>Name</b>" TEXT="#name#"> <cfcol header="<B>Path</b>" TEXT="#path#"> <cfcol header="<B>URL</b>" TEXT="#url#"> <cfcol header="<B>Length</b>" TEXT="#length#"> <cfcol header="<B>LastModified</b>" TEXT="#DateFormat(lastmodified)#"> <cfcol header="<B>IsDirectory</b>" TEXT="#isdirectory#"> </cftable>
hafter you establish a connection with cfftp, you can reuse the connection to perform additional FTP operations until either you or the server closes the connection. When you access an already-active FTP connection, you do not need to re-specify the username, password, or server. In this case, make sure that when you use frames, only one frame uses the connection object.
Note
For a single simple FTP operation, such as GetFile or PutFile, you do not need to establish a connection. Specify all the necessary login information, including the server and any login and password, in the single cfftp request.
344
Assigning a cfftp connection to an Application variable could cause problems, since multiple users could access the same connection object at the same time. Creating a Session variable for a cfftp connection makes more sense, because the connection is available to only one client and does not last past the end of the session.
In this example, the connection cache remains available to other pages within the current session. You must enable Session variables in your application for this approach to work, and you must lock code that uses Session variables. For information on locking, see Locking Code with cflock on page 233.
Note
Changing a connections characteristics, such the retrycount or timeout values, might require you to re-establish the connection.
345
346
objects on a remote system. Communication between objects on remote systems uses an efficient, special-purpose wire protocol. In the disconnected world, however, these services are a barrier to development. At the most fundamental level, the wire protocols of Distributed COM and CORBA are blocked by most Web firewall software. The largest barrier, though, is that client-server-oriented distributed computing frameworks impose a development methodology that is radically different from that of the Web. This methodology excludes the vast majority of developers building Web applications whose main tools are tag-based markup languages and scripting. While WDDX works with systems that support component object development paradigms, there is a large set of applications that can benefit from the general characteristics of a distributed data system without the client-server overhead.
WDDX components
WDDX is based on XML, which is a World Wide Web Consortium (W3C) Recommendation. The core of WDDX is an XML vocabulary, a set of components for each of the target platforms to serialize and deserialize data into the appropriate data structure, and a document type definition (DTD) that describes the structure of standard data types. Functionally, this creates a way to move data, its associated data
347
types, and descriptors that allow the data to be manipulated on a target system between arbitrary application servers. When you use WDDX in ColdFusion pages, you typically use the ColdFusion cfwddx tag and the JavaScript utility classes that are installed as /CFIDE/scripts/wddx.js on your local host.
348
In the CFML implementation, useTimezoneInfo is an attribute of the cfwddx action=cfml2wddx tag. In the JavaScript implementation, useTimezoneInfo (note the case sensitivity of JavaScript) is a property of the WddxSerializer object. Date-time values in WDDX are represented using a subset of the ISO8601 format. Time zone information is represented as an hour/minute offset from UTC; for example, 1998-9-8T12:6:26-4:0. During WDDX deserialization to CFML, time zone information is automatically taken into account and all date-time values are converted to local time. In this way, UTC is taken out of the picture entirely and you do not need to worry about the details of time zone conversions. However, during deserialization to JavaScript expressions, time zone information is not taken into account. Complications arise because of the difficulty of determining the time zone of the browser.
When the WDDX Deserializer object deserializes this XML, it creates a structure that is also created by either of the following scripts: JavaScript
x = new Object(); x.a = "Property a"; x.b = "Property b";
CFScript
x = structNew(); x.a = "Property a"; x.b = "Property b";
The WddxSerializer and WddxDeserializer objects are defined in the file CFIDE/ scripts/wddx.js. For detailed information on these JavaScript objects, see the CFML Reference.
349
Note
To see how cfwddx Action="cfml2js" works, view the source to the page in your browser.
350
351
// Person info record set with columns firstName and lastName // Make sure the case of field names is preserved var personInfo = new WddxRecordset(new Array("firstName", "lastName"), true); // Add next record to end of personInfo record set function doNext() { // Extract data var firstName = document.personForm.firstName.value; var lastName = document.personForm.lastName.value; // Add names to record set nRows = personInfo.getRowCount(); personInfo.firstName[nRows] = firstName; personInfo.lastName[nRows] = lastName; // Clear input fields document.personForm.firstName.value = ""; document.personForm.lastName.value = ""; // Show added names on list // This gets a little tricky because of browser differences var newName = firstName + " " + lastName; if (navigator.appVersion.indexOf("MSIE") == -1) { document.personForm.names[length] = new Option(newName, "", false, false); } else { // IE version var entry = document.createElement("OPTION"); entry.text = newName; document.personForm.names.add(entry); } } </script>
<!--- Data collection form ---> <form action="wddx_browser_2_server.cfm" method="Post" name="personForm"> <!--- Input fields ---> Personal information<p> First name: <input type=text name=firstName><BR> Last name: <input type=text name=lastName><BR> <p>
352
<!--- Navigation & submission bar ---> <input type="button" value="Next" onclick="doNext()"> <input type="button" value="Serialize" onclick="serializeData(personInfo, document.personForm.wddxPacket)"> <input type="submit" value="Submit"> <P> Names added so far:<br> <select name="names" size="5"> </select> <p></p> <!--- This is where the WDDX packet will be stored ---> <!--- In a real application this would be a hidden input field. ---> WDDX packet display:<p> <textarea name="wddxPacket" rows="10" cols="80" wrap="Virtual"> </textarea> </form>
<!--- Server-side processing ---> <hr> <p><B>Server-side processing</B></p> <cfif isdefined("form.wddxPacket")> <cfif form.wddxPacket neq ""> <!--- Deserialize the WDDX data ---> <cfwddx action="wddx2cfml" input=#form.wddxPacket# output="personInfo"> <!--- Display the query ---> The submitted personal information is:<P> <cfoutput query=personInfo> Person #CurrentRow#: #firstName# #lastName#<BR> </cfoutput> <cfelse> The client did not send a well-formed WDDX data packet! </cfif> <cfelse> No WDDX data to process at this time. </cfif>
353
<!--- Now read the data from client scope into a new structure ---> <cfwddx action="wddx2cfml" input="#Client.wddxRelatives#" output="sameRelatives"> A dump of the sameRelatives structure <br> generated from client.wddxRelatives<br> <br> <cfdump var="#sameRelatives#">
354
Chapter 19
Application Security
ColdFusion supports several levels of security. This chapter explains how to deploy user security, which offers runtime security for ColdFusion applications. It also describes the Remote Development Services security feature, which authenticates developers accessing server resources through ColdFusion Studio. For information on setting up security elements or using Administrator-controlled security features, see Advanced ColdFusion Administration.
Contents
ColdFusion Security Features ................................................................................ 356 Remote Development Services (RDS) Security..................................................... 356 Overview of User Security....................................................................................... 357 Using Advanced Security in Application Pages..................................................... 358 Using the cfauthenticate tag .................................................................................. 359 Authentication and Authorization Functions....................................................... 360 Catching Security Exceptions................................................................................. 361 Using the cfimpersonate Tag.................................................................................. 362 Example of User Authentication and Authorization ............................................ 363
356
357
358
359
Example
<cfauthenticate securitycontext="MyAppSecurityContextName" username=#userID# password=#pwd#>
If the user is not already defined in the system, ColdFusion throws a Security exception. You can either reject access to the resource or reroute the user to a login page. For example, you can display a login form and then, if the user logs in successfully, display the originally requested page. For a longer code example, see Example of User Authentication and Authorization on page 363.
360
follows:
IsAuthorized(ResourceType, ResourceName, [ResourceAction])
For example, to check whether the authenticated user is authorized to update a data source resource called orders, use this syntax:
IsAuthorized("Datasource", "orders", "update")
In this example, the IsAuthorized function returns True if the user is authorized to update the named data source, or if the data source is not protected in the security context.
361
Note The ColdFusion Server does not check user authorization unless you specifically request it with the IsAuthorized function. It is up to you to decide what action to take based on the results of the IsAuthorized call.
Example
This example shows the use of exception handling with cfauthenticate in an Application.cfm file. The cfauthenticate tag authenticates a user and sets the security context for an application. If the user is not already defined in the system, you can either reject the page, request that the user respecify the username and password, or define a new user. The following example just rejects the page request and displays a message:
<html> <head> <title>cfauthenticate Example</title> </head> <body> <h3>cfauthenticate Example></h3> <!--- This code is from an Application.cfm file ---> <cftry> <cfauthenticate securityContext="MyApplicationSC" username=#user# password=#pwd#> <cfcatch type="Security"> <!--- The message to display ---> <h3>Authentication error</h3> <!--- display a message. Alternatively, you might place code here to define the user to the security context. ---> <cfoutput> <p>#cfcatch.Message#</p> </cfoutput>
362
counter, you must let them read specific, system-maintained files, in this case, the file that contains number of hits to the customers home page. You can provide the hit-counter in a custom tag that uses the cffile tag. To ensure that the custom tag can access the cffile tag, it needs a way to impersonate a trusted user while the tag is executing and then to revert back to the nontrusted user after the trusted piece of code executes. The cfimpersonate tag has the following required attributes: securitycontext Describes which security context to use for authentication and authorization. This name matches the security context as defined on the Advanced Security page of the ColdFusion Administrator. username The username of the user to impersonate. password The password of the user to impersonate. type Indicates the type of impersonation to implement, CF for application level or OS for operating system level. Application-level impersonation lets you assume the rights assigned to a ColdFusion user by a specified security context. Operating-system-level impersonation lets you assume the rights assigned to a Windows NT user by a specified Windows NT domain. Operating-system-level impersonation is not currently available for UNIX. In addition, cfimpersonate has one optional attribute: throwOnFailure Indicates whether ColdFusion throws an exception of type Security if authentication fails. Default is Yes.
363
Example
The following example reads a protected file because the ColdFusion user pfoley has been granted access to the file by the security context MyContext. If the user cannot be authenticated, ColdFusion throws a Security exception.
<cfimpersonate securitycontext="MyContext" username="pfoley" password="admin" type= "CF" throwonfailure= "Yes"> <cffile file="#readFile#" action="read" variable="text"> <cfoutput> The file contains the following text:<br>#text#<br> </cfoutput> </cfimpersonate>
364
response is checked against the list of valid users defined for the current security context. If the user passes the authentication step, the requested page appears. The application uses the CGI variables script_name and query_string to keep track of the originally requested page so that it can display that page after the user is authenticated. All pages governed by this Application.cfm page those in the same directory as Application.cfm and in its subtree automatically invoke this authentication test. Note To use this code in your own Application.cfm page, change the application name and security context name to match your application and security names.
Example: Application.cfm
<cfapplication name="Orders"> <cfif NOT IsAuthenticated()> <!--- The user is not authenticated ---> <cfset showlogin="No"> <cfif IsDefined("form.username") AND IsDefined("form.password")> <!--- The login form was submitted. Try authenticating ---> <cftry> <cfauthenticate securityContext="Orders" username="#form.username#" password="#form.password#" setCookie="YES"> <cfcatch type="security"> <!--- Security error in login occurred. Show login again ---> <h3>Invalid Login</h3> <cfset showLogin="Yes"> </cfcatch> </cftry> <cfelse> <!--- The login was not detected. Show login again---> <cfset showlogin="Yes"> </cfif> <!--- Show the login form ---> <cfif showlogin> <!--- Recreate the url used to call the requested page ---> <cfset url="#cgi.script_name#"> <cfif cgi.query_string IS NOT ""> <cfset url=url & "?#cgi.query_string#"> </cfif>
365
<!--- The login form. Submitting the form re-requests the originally requested page using the recreated url ---> <cfoutput> <form action="#url#" method="Post"> <table> <tr> <td>username:</td> <td><input type="text" name="username"></td> </tr> <tr> <td>password:</td> <td><input type="password" name="password"></td> </tr> </table> <input type="submit" value="Login"> </form> </cfoutput> <cfabort> </cfif> </cfif>
Example: orders.cfm
<!--- First, check whether a form button was submitted ---> <cfif IsDefined("Form.btnUpdate")> <!--- Is user is authorized to update or select information from the Orders data source? ---> <cfif IsAuthorized("DataSource", "Orders", "update")> <cfquery name="AddItem" datasource="Orders"> INSERT INTO Orders (Customer, OrderID) VALUES #Customer#, #OrderID# </cfquery> <cfoutput query="AddItem"> Authorization Succeeded. Order information added: #Customer# - #OrderID#<br> </cfoutput> <cfelse> <cfabort showerror="You are not allowed to update order information."> </cfif>
366
</cfif> <cfif IsAuthorized("DataSource", "Orders", "select")> <cfquery name="GetList" datasource="Orders"> SELECT * FROM Orders </cfquery> Authorization Succeeded. Order information follows: <cfoutput query="GetList"> #Customer# - #BalanceDue#<br> </cfoutput> <cfelse> <cfabort showerror="You cannot view order information."> </cfif>
Chapter 20
This chapter describes how to use the cfobject tag to invoke objects created by component technologies, including COM/DCOM, CORBA, and Java objects.
Contents
Component Object Overview................................................................................. 368 Invoking Component Objects ................................................................................ 369 Getting Started with COM/DCOM......................................................................... 370 Creating and Using COM Objects .......................................................................... 374 Getting Started with CORBA................................................................................... 376 Calling CORBA Objects ........................................................................................... 376 Calling Java Objects................................................................................................. 378
368
About COM
COM (Component Object Model) is a specification and a set of services defined by Microsoft to enable component portability, reusability, and versioning. DCOM (Distributed Component Object Model) is an implementation of COM for distributed services, allowing access to components residing on a network. COM objects can reside locally or on any network node. Currently, COM is supported on Windows NT 3.51/4.0 and Windows 95/98.
Resources
To find out more about COM/DCOM, go toMicrosofts COM site, http:// www.microsoft.com/com.
About CORBA
CORBA (Common Object Request Broker Architecture) is a specification for a distributed component object system defined by the Object Management Group (OMG). In this model, an object is an encapsulated entity whose services are accessed only through well-defined interfaces. The location and implementation of each object is hidden from the client requesting the services. ColdFusion supports CORBA 2.0 on both Windows and UNIX.
Resources
The OMG site, http://www.omg.com, is the main Web repository for CORBA information.
369
Using properties
Use the following coding practices to access properties.
To set a property:
<cfset obj.property = "somevalue">
To get a property:
<cfset value = obj.property>
Note that parentheses are not used on the right side of the equation for property-gets.
Calling methods
Object methods usually take zero or more arguments. Arguments can be sent by value ([in] arguments) or by reference ([out] and [in,out]). Arguments sent by reference usually have their value changed by the object. Some methods return values, while others may not.
This method accepts one integer argument and one string argument.
Note the use of double-quotation marks (") to specify reference arguments. If the object changes the value of "x", it now contains a value other than 23.
370
371
You typically register local servers (*.exe) either by starting them or specifying a command line parameters, such as the following:
C:\pathname\servername.exe -register
372
2 3
Select and expand the object in the Object Viewer. Right-click the object to view it.
373
If you view the TypeInfo, you see the objects methods and properties. Some objects do not have access to the TypeInfo area. This is determined when an object is built and by the language used.
374
Note CDO is installed by default on all Windows NT and 2000 operating systems that have installed the Microsoft SMTP server. In Windows NT Server environments, the SMTP server is part of the Option Pack 4 set up. In Windows 2000 Server and Workstation environments, it is bundled with the operating system. For more information on CDO for NTS, see http://msdn.microsoft.com/library/default.asp?URL=/library/ psdk/cdo/_olemsg_overview_of_cdo.htm. You must create the component in ColdFusion before your application pages can invoke any methods or assign any properties in the component. This sample CDO for NTS NewMail component includes a number of methods and properties to perform a wide range of mail-handling tasks. (In the OLE/COM Viewer, methods and properties might be grouped together, so you might find it difficult to distinguish between them at first.) The CDO for NTS NewMail object includes the following properties:
Body [ string ] Cc [ String ] From [ String ] Importance [ Long ] Subject [ String ] To [ String ]
You use these properties to define elements of the mail message you want to send. The CDO for NTS NewMail object also includes a method with a number of optional arguments to send messages:
Send()
375
local An out-of-process server object (typically an exe file) that is running outside the ColdFusion process space but running locally on the same server. remote An out-of-process server object (typically an exe file) that is running remotely on the network. If you specify remote, you must also use the server attribute to identify where the object resides.
Note Use the cftry and cfcatch tags to handle exceptions thrown by COM objects. For more information on exception handling, see Handling Exceptions in ColdFusion on page 204.
376
377
Example
Here is the IDL for an object:
struct SimpleStruct { short s; long l; float d; }; struct NestedStruct { SimpleStruct f; char c; string s; }; typedef sequence<long, 5> BLongSequence; interface SomeObject { short SomeMethod( in NestedStruct inStruct, };
in BlongSequence inSeq);
378
Exception handling
You can catch exceptions thrown by the CORBA object methods with the cftry and cfcatch tags. However, you cannot extract information from the exception object.
Although this tag loads the class, it does not create an instance object. Static methods and fields are accessible after the call to cfobject. To call the constructors explicitly, use the init method with the appropriate arguments; for example:
<cfset ret=myObj.init(arg1, arg2)>
If you call a public method on the object without first calling the init method, the result is an implicit call to the default constructor. Arguments and return values can be any valid Java type; for example, simple arrays and objects. ColdFusion does the appropriate conversions when strings are passed as arguments, but not when they are received as return values. The following sections provide more details on calling Java objects in ColdFusion.
public Employee() {
379
FirstName =""; LastName =""; Salary = 0.0f; JobGrade = 0; } public Employee(String First, String Last) { FirstName = First; LastName = Last; Salary = 0.0f; JobGrade = 0; } public Employee(String First, String Last, float salary, int grade) { FirstName = First; LastName = Last; Salary = salary; JobGrade = grade; } public void SetSalary(float Dollars) { Salary = Dollars; } public float GetSalary() { return Salary; } public void SetJobGrade(int grade) { JobGrade = grade; } public void SetJobGrade(String Grade) { if (Grade.equals("CEO")) { JobGrade = 3; } if (Grade.equals("MANAGER")) { JobGrade = 2; } if (Grade.equals("DEVELOPER")) { JobGrade = 1; } } public int GetJobGrade() { return JobGrade; } }
380
#firstname# #lastname#
When you view the page in your browser, you should get the following output: Employee name is john doe
Description Load an instance of the Employee Java class named emp. Do not call a constructor. ColdFusion invokes the default constructor when it first uses the class; in this case, when it processes the next line. Set the public fields in the emp object to your values. Get the field values back from emp object. Display the retrieved values.
#firstname#
<cfset emp.firstname="john"> <cfset emp.lastname="doe"> <cfset firstname=emp.firstname> <cfset lastname=emp.lastname> <cfoutput> Employee name is #lastname# </cfoutput>
Java considerations
Keep the following points in mind when you write a ColdFusion page that uses a Java class object: The Java class name is case sensitive. You must make sure that both the Java code and the CFML code use Employee as the class name.
381
Java method and field names are not case sensitive. Similarly, ColdFusion variables are not case sensitive. As a result, the sample code works even though the CFML uses emp.firstname and emp.lastname, while the Java source code uses FirstName and LastName for these fields. If you omit a call to the constructor (or, as in this example, comment it out) ColdFusion automatically invokes the default constructor when it first uses the class.
In this example, the constructor takes four arguments; the first two are strings, and third is a float, and the fourth is an integer.
382
The 1 could be interpreted as string or as number, so there is no way to know which method implementation to use. When a ColdFusion encounters such an ambiguity, it throws a user exception. The ColdFusion JavaCast function helps you resolve such issues by specifying the Java type of a variable, as in the following line:
<cfset emp.SetJobGrade(JavaCast(int, 1)>
The JavaCast function takes two parameters: a string representing the Java data and the variable whose type your are setting. You can specify the following Java data types: bool, int, long, float, double, and String. For more information on the JavaCast function, see CFML Reference.
Exception Handling
Use the cftry and cfcatch tags to can catch exceptions thrown by Java objects. Use the CFML GetException function to retrieve the Java exception object. The following example demonstrates the GetException function.
383
Description Load an instance of the Java foo class named Obj. Inside a cftry block. call the doException method of the Obj object. This method throws an exception of the fooException type.
384
Code
<cfcatch type="Any"> <cfset exception=GetException(Obj)> <cfset message=exception.GetERrorMessage( )> <cfoutput> <br>The exception message is: #message#<br> </cfoutput>
Description Catch any exceptions and handle them in this block. Get the exception data by calling the CFML GetException function and passing it the Obj object. Set the message variable to the string returned by the exception objects GetErrorMessage method. Output the message string.
Note that after you call GetException, the exception object is just like any other Java component object, and you can call any methods on it.
385
To disable automatic class loading, put all classes in the normal Java class path. Classes located on the Java class path are loaded once per server lifetime and can only be reloaded by stopping and restarting ColdFusion Server.
SumArray SumObjArray
ReverseArray Flip
public class Example { public int mPublicInt; public Example() { mPublicInt = 0; } public Example(int IntVal) { mPublicInt = IntVal; } public String ReverseString(String s) { StringBuffer buffer = new StringBuffer(s); return new String(buffer.reverse()); } public String[] ReverseStringArray(String [] arr) {
386
String[] ret = new String[arr.length]; for (int i=0; i < arr.length; i++) { ret[arr.length-i-1]=arr[i]; } return ret; } public int Add(int a, int b) { return (a+b); } public float Add(float a, float b) { return (a+b); } public Example Add(Example a, Example b) { return new Example(a.mPublicInt + b.mPublicInt); } static public int SumArray(int[] arr) { int sum=0; for (int i=0; i < arr.length; i++) { sum += arr[i]; } return sum; } static public Example SumObjArray(Example[] arr) { Example sum= new Example(); for (int i=0; i < arr.length; i++) { sum.mPublicInt += arr[i].mPublicInt; } return sum; } static public int[] ReverseArray(int[] arr) { int[] ret = new int[arr.length]; for (int i=0; i < arr.length; i++) { ret[arr.length-i-1]=arr[i]; } return ret; }
387
<!--- Use the Java object to flip a Boolean value, reverse a string, add two integers, and add two float numbers ---> <cfset c=obj.Flip(true)> <cfset StringVal=obj.ReverseString("This is a test")> <cfset IntVal=obj.Add(JavaCast("int",20),JavaCast("int",30))> <cfset FloatVal=obj.Add(JavaCast("float",2.56),JavaCast("float",3.51))> <!--- Display the results ---> <cfoutput> <br> StringVal: #StringVal#<br> IntVal: #IntVal#<br> FloatVal: #FloatVal#<br> <br> </cfoutput>
388
<!--- Create a two-element array, sum its values, and reverse its elements ---> <cfset intarray=ArrayNew(1)> <cfset intarray[1]=1> <cfset intarray[2]=2> <cfset IntVal=obj.sumarray(intarray)> <cfset reversedarray=obj.ReverseArray(intarray)> <!--- Display the results ---> <cfoutput> <br> IntVal1 :#IntVal#<br> array1: #reversedarray[1]#<br> array2: #reversedarray[2]#<br> <br> </cfoutput><br>
<!--- Create a ColdFusion array containing two Example objects. Use the SumObjArray method to add the objects in the array Get the public member of the resulting object---> <cfset oa=ArrayNew(1)> <cfobject action=create type=java class=Example name=obj1> <cfset VOID=obj1.init(JavaCast("int",5))> <cfobject action=create type=java class=Example name=obj2> <cfset VOID=obj2.init(JavaCast("int",10))> <cfset oa[1] = obj1> <cfset oa[2] = obj2> <cfset result = obj.SumObjArray(oa)> <cfset intval = result.mPublicInt> <!--- Display the results ---> <cfoutput> <br> intval1: #intval#<br> <br> </cfoutput><br> </body> </html>
Chapter 21
Sometimes, the best approach is to develop elements of your application by building executables to run with ColdFusion. Perhaps the application requirements go beyond what is currently feasible in CFML. Perhaps you can improve application performance for certain types of processing. To meet these types of requirements, you can use the ColdFusion Extension Application Programming Interface (CFXAPI) to access ColdFusion functions. This chapter documents custom tag development using Java or C++, however, it is also possible to develop tags in Borlands Delphi.
Contents
What Are CFX Tags?................................................................................................. 390 Before You Begin Developing CFX Tags in Java..................................................... 391 Writing a Java CFX ................................................................................................... 393 ZipBrowser Example ............................................................................................... 397 Approaches to Debugging Java CFXs..................................................................... 398 Customizing and Configuring Java ........................................................................ 392 Developing CFX Tags in C++ .................................................................................. 401 Registering CFXs...................................................................................................... 404 Distributing CFX Tags ............................................................................................. 405
390
Note
To use a CFX, you must register it in the ColdFusion Administrator, as described in Registering CFXs on page 404.
391
392
The classes directory created by the ColdFusion setup program serves two purposes: It contains the supporting classes required for developing and deploying Java CFXs. This is the com.allaire.cfx package located in the cfx.jar archive. It supports a feature that allows Java CFXs located in the directory to be reloaded every time they are changed. Although this is not the default behavior for other Java classes, this behavior is very useful during an iterative development and testing cycle. When you create new Java CFXs, you should develop and deploy them in the
classes directory. Following this guideline will dramatically simplify your
development, debugging, and testing processes. Once you are finished with development and testing, you can then deploy your Java CFX anywhere on the class path visible to the ColdFusion embedded JVM. See Customizing and Configuring Java for more details on customizing the class path.
393
3 4
Save the file as HelloColdFusion.java in the classes subdirectory. Compile the java source file into a class file using the Java compiler. If you are using the command-line tools bundled with the JDK, use the following command line, which you execute from within the classes directory:
javac -classpath cfx.jar HelloColdFusion.java
Note
The previous command works only if the Java compiler (javac.exe) is in your path. If it is not in your path, specify the fully qualified path; for example, c:\jdk12\bin\javac on Windows NT or /usr/java/bin/javac on UNIX. If you receive errors during compilation, check the source code to make sure you entered it correctly. If no errors occur, you just successfully wrote your first Java CFX. As you can see, implementing the basic CustomTag interface is straightforward. This is all a Java class must do to be callable from a CFML page.
Processing requests
Implementing a Java CFX requires interaction with the Request and Response objects passed to the processRequest method. In addition, CFXs that need to work with ColdFusion queries also interface with the Query object. The com.allaire.cfx package, located in the classes/cfx.jar archive, contains the Request, Response, and Query objects.
394
This section provides an overview of these object types. For a complete example Java CFX that uses Request, Response, and Query objects, see the ZipBrowser Example on page 397.
Request object
The Request object is passed to the processRequest method of the CustomTag interface. It provides methods for retrieving attributes, including queries, passed to the tag and for reading global tag settings. Method attributeExists getAttribute getIntAttribute getAttributeList getQuery getSetting debug Description Checks whether the attribute was passed to this tag. Retrieves the value of the passed attribute. Retrieves the value of the passed attribute as an integer. Retrieves a list of all attributes passed to the tag. Retrieves the query that was passed to this tag, if any. Retrieves the value of a global custom tag setting. Checks whether the tag contains the debug attribute.
Response object
The Response object is passed to the processRequest method of the CustomTag interface. It provides methods for writing output, generating queries, and setting variables within the calling page. Method
write setVariable addQuery writeDebug
Description Outputs text into the calling page. Sets a variable in the calling page. Adds a query to the calling page. Outputs text into the debug stream.
Query object
The Query object provides an interface for working with ColdFusion queries. It includes methods for retrieving name, row count, and column names and methods for getting and setting data elements. Method
getName getRowCount getColumns getData
Description Retrieves the name of the query. Retrieves the number of rows in the query. Retrieves the names of the query columns. Retrieves a data element from the query.
395
Method
addRows setData
Description Adds a new row to the query. Sets a data element within the query.
For detailed reference information on each of these interfaces, see the CFML Reference.
Description Automatically reload Java CFX and dependent classes within the classes directory whenever the CFX class file changes. Does not reload if a dependent class file changes but the CFX class file does not change. Always reload Java CFX and dependent classes within the classes directory. Ensures a reload even if a dependent class changes, but the CFX class file does not change. Never reload Java CFX classes. Load them once per server lifetime.
Always
Never
396
The default value is reload="Auto". This is appropriate for most applications. Use reload="Always" during the development process when you must ensure that you always have the latest class files, even when only a dependent class changed. Use reload="Never" to increase performance by omitting the check for changed classes.
Note
The reload attribute applies only to class files located in the classes directory. The ColdFusion server loads classes located on the Java class path once per server lifetime. You must stop and restart ColdFusion Server to reload these classes. For information on loading Java class files, see The class loading mechanism on page 384.
3 4
ZipBrowser Example
397
ColdFusion processes the page and returns a page that displays the text Hello, Robert. If an error is returned instead, check the source code to make sure you have entered it correctly.
ZipBrowser Example
The following example illustrates the use of the Request, Response, and Query objects. The example uses the java.util.zip package to implement a Java CFX called ZipBrowser, which is a zip file browsing tag. The tags archive attribute specifies the fully qualified path of the zip archive to browse. The tags name attribute must specify the query to return to the calling page. The returned query contains three columns: Name, Size, and Compressed. For example, to query an archive at the path C:\logfiles.zip for its contents and output the results, you use the following CFML code:
<cfx_ZipBrowser archive="C:\logfiles.zip" name="LogFiles" > <cfoutput query="LogFiles"> #Name#, #Size#, #Compressed# <BR> </cfoutput>
public class ZipBrowser implements CustomTag { public void processRequest( Request request, Response response ) throws Exception { // validate that required attributes were passed if ( !request.attributeExists( "ARCHIVE" ) || !request.attributeExists( "NAME" ) ) { throw new Exception( "Missing attribute (ARCHIVE and NAME are both " + "required attributes for this tag)" ) ; } // get attribute values String strArchive = request.getAttribute( "ARCHIVE" ) ; String strName = request.getAttribute( "NAME" ) ; // create a query to use for returning the list of files String[] columns = { "Name", "Size", "Compressed" } ; int iName = 1, iSize = 2, iCompressed = 3 ; Query files = response.addQuery( strName, columns ) ;
398
// read the zip file and build a query from its contents ZipInputStream zin = new ZipInputStream( new FileInputStream(strArchive) ) ; ZipEntry entry ; while ( ( entry = zin.getNextEntry()) != null ) { // add a row to the results int iRow = files.addRow() ; // populate the row with data files.setData( iRow, iName, entry.getName() ) ; files.setData( iRow, iSize, String.valueOf(entry.getSize()) ) ; files.setData( iRow, iCompressed, String.valueOf(entry.getCompressedSize()) ) ; // finish up with entry zin.closeEntry() ; } // close the archive zin.close() ; } }
399
If you need to debug a Java CFX while running against a live production server, this is the technique you must use. In addition to outputting debug text using the Response.write method, you can also call your Java CFX tag with the debug="On" attribute. This attribute flags the CFX that the request is running in debug mode and therefore should output additional extended debug information. For example, to call the HelloColdFusion CFX in debug mode, use the following CFML code:
<cfx_HelloColdFusion" name="Robert" debug="On">
To determine whether a CFX is invoked with the debug attribute, use the Request.debug method. To write debug output in a special debug block after the tag finishes executing, use the Response.writeDebug method. For details on using these methods, see the CFML Reference.
After you implement a main method as described previously, you can debug your Java CFX using an interactive, single-step debugger. Just specify your Java CFX class as the main class, set breakpoints as appropriate, and begin debugging.
400
// create tag, process debug request, and print results OutputQuery tag = new OutputQuery() ; DebugRequest request = new DebugRequest( attributes, query ) ; DebugResponse response = new DebugResponse() ; tag.processRequest( request, response ) ; response.printResults() ; } catch( Throwable e ) { e.printStackTrace() ; } } public void processRequest( Request request ) throws Exception { // ...code for processing the request... } }
401
Before you can use your C++ compiler to build custom tags, you must enable the compiler to locate the CFXAPI header file, cfx.h. On Windows NT, you do this by adding the CFXAPI Include directory to your list of global include paths. On Windows, this directory is \cfusion\cfx\include. On UNIX it is /opt/coldfusion/cfx/ include. On UNIX, you will need -I <includepath> on your compile line (see the Makefile for the directory list example in the cfx/examples directory).
402
The next step is to make ColdFusion aware of the new tag by registering it. See Registering CFXs on page 404.
On Windows NT
You can easily debug custom tags within the Visual C++ environment. To debug a tag, open the Build Settings dialog box and click the Debug tab. Set the Executable for debug session setting to the full path to the ColdFusion Engine (such as, c:\cfusion\bin\cfserver.exe) and set the program arguments setting to -DEBUG.
403
On UNIX
Use the following debuggers and settings for the supported UNIX operating systems: OS Solaris Debugger dbx Other OS-specific requirements The environment variables must include
LD_LIBRARY_PATH and CFHOME.
Use stop in main to set a breakpoint in main. Linux gdb The environment variables must include LD_LIBRARY_PATH and CFHOME. Use break main to set a breakpoint in main. The environment variables must include SHLIB_PATH and
CFHOME.
HP-UX
DDE
Use stop in main to set a breakpoint in main. Shut down ColdFusion using the stop script. Set the environment variables as they are set in the start script. You can then run the cfserver executable under the dbx debugger and set breakpoints in your CFX code. You might need to set a breakpoint in main so the debugger loads the symbols for your CFX before you can set breakpoints in your code.
404
Registering CFXs
To use a CFX tag in your ColdFusion applications, first register it in the Extensions, CFX Tags page in the ColdFusion Administrator.
You can now call the tag from a ColdFusion page. On Windows NT only, the Visual C++ Custom Tag Wizard automatically registers custom tags so that they can be tested and debugged.
405
Value
HKEY_LOCAL_MACHINE SOFTWARE\Allaire\ColdFusion\CurrentVersion\CustomTags\ TagName
The name of the class to call. A description of the tags functionality for browsing by end users.
The following table lists the registry entries for C++: Entry
Hive Key LibraryPath
Value
HKEY_LOCAL_MACHINE SOFTWARE\Allaire\ColdFusion\CurrentVersion\CustomTags\
TagName The full path to the DLL (Windows NT) or shared object (UNIX) that implements the custom tag. The name of the procedure to call for processing tag requests. A description of the tags functionality for browsing by end users. Indicates whether to keep the DLL or shared object loaded in RAM (1 or 0).
You can create a file containing this information by using the Windows Regedit utility to export the registry entry from a machine on which the custom tag is already installed. On Windows NT, use Regedit to import custom tags to the registry. On UNIX you must edit the registry data file, located in /opt/coldfusion/registry/cf.registry.
406
In the install script, import the registry entry by including the following command in the install script:
regedit importfilename
In the install script, import the registry entry by including the following command in the install script:
regedit importfilename
Index
Special
#,using 14 , in search expressions
288
A
Accessing Client variables 225 collections 298 data sources 21 generated content 187 Action pages 45 Active Server Pages 345 Adding data elements to structures data sources 22 elements to an array 119 Administrative lock management 236 Advanced security, implementing 358 Ancestor tags data access 182 definition 180 AND operator SQL, definition 27 SQL, using 52 Appearance, of graphs 67 Application 215 Application framework about 214 approaches to 217 custom error pages 199 description 214 mapping 216 Application pages creating 10 description 6, 10 errors 199 naming 4, 16
127
processing 8 saving 11 viewing 11 Application scope 215 Application servers, data exchange across 347 Application variables description 215 lifetime of 231 listing 231 time-outs 231 usage tips 231 using 230 Application.cfm file application security 363 application-level settings 219 creating 219 custom functions in 254 processing 216 Application-level data, and WDDX 347 Application-level settings 214 Applications development considerations 16 development process 10 directory structure 216, 217 error handling in 215 naming 219 storing variables 230 Area graphs, setting appearance 74 Arguments custom function 251 optional 251 passing 252 ArrayAppend CFML function 119 ArrayDeleteAt CFML function 118 ArrayInsertAt CFML function 119
ArrayNew CFML function 119 ArrayPrepend CFML function 119 Arrays 2-dimensional 116 3-dimensional 116 adding data to 118 adding elements to 118, 119 associative 125 creating 118 description 116 dimensions 117 elements 117 functions 124 index 117 multidimensional 119 passing to functions 255 populating 121 referencing elements in 119 resizing 118 ArraySet CFML function 121 ArraySort CFML function 129 Assignment, CFscript statements 245 Attaching MIME files 307 Attributes checking 194 for custom tags 175 passing values 176, 177 Attributes scope 174 Authentication checking for 365 example 364 functions 360 using Application.cfm 363 Authorization checking for 365 functions 360 Automatic read locking 236 AVG SQL function 65
408
Index
B
Backreferences about 265 in regular expression searches 142 in replacement strings 265 Bar charts, specifying appearance 68 Base tags 180 BETWEEN SQL Operator 27 Binary files, saving 334 break, CFScript statement 248 Browsers cfform considerations 138 displaying e-mail in 309 transferring data to a server 350 Building drop-down list boxes 166 queries 28 search interfaces 52, 279 slider bar controls 164 text entry boxes 165 tree controls 147 Built-in variables Client 225 custom tags 185 Server 232 Session 229
C
C++ CFX tags implementing 402 importing 406 C++ development environment 401 Caching connections 343 Caller scope description 174 using 176 Calling CFX tags 396 CORBA objects 376 custom functions 251 Java objects 378 nested objects 370 object methods 369 Catching security exceptions 361 cfabort tag, and OnRequestEnd.cfm 216 cfapplet tag description 137 using 167, 169 cfapplication tag 222 cfassociate tag 181
cfauthenticate tag and Web security 215 example 363 syntax 359 using 359 using setcookie 359 cfcatch tag 204 cfcollection tag 274 cfcontent tag 341 cfdirectory tag and queries 34 for file operatons 341 cfelse tag 96 cfelseif tag 96 cfencode utility 189 cferror page 199 cferror tag 215 cfexit tag and OnRequestEnd.cfm 216 behavior of 186 cffile tag 318 cfflush tag and HTML headers 57 using 56 cfform controls browser considerations 138 description 137 cfform tag passthrough attribute 136 usage notes 138 using with HTML 136 cfftp tag attributes 344 connection actions 344 using 341 cfgraph tag basic usage 61 common attributes 67 for bar charts 68 for line graphs 74 for pie charts 71 graphing queries 62 introduced 60 cfgraphdata tag 66 cfgrid tag browser considerations 138 controlling cell contents 156 editing data in 157 handling failed validaton 144 returning user edits 156 using 153 validating with Javascript 144 cfhttp tag and queries 34
creating queries 335 Get method 332 Post method 332, 337 using 332 cfhttpparam tag 337 CFID Cookie 222 managing without cookies 222 Server-side variable 222 cfif tag 52, 96 cfimpersonate tag 362 cfinclude tag and Application.cfm 216 using 172 cfindex tag and queries 34 extermal attribute 276 indexing collections 278 cfinput tag handling failed validaton 144 passthrough attribute 136 validating with Javascript 144 cfinsert tag creating action pages 103 form considerations 103 inserting data 102 cfldap tag and queries 34 indexing queries 282 cflocation tag 226 cflock tag controlling time-outs 235 examples 238 for file access 241 name attribute 235 nesting 237 scope attribute 234 throwOnTimeout attribute 235 time-out attribute 235 using 233 cfloop tag emulating in custom tags 186 nested 122 cfmail tag sample uses 304 sending mail as HTML 308 cfmailparam tag 307 CFML application pages 10 code validation 194 converting data to JavaScript 349 definition 7 extending 390
Index
409
interaction with CFScript 249 syntax checker 194 syntax errors 195 CFML expressions,in CFScript 245 CFML functions ArrayAppend 119 ArrayDeleteAt 118 ArrayInsertAt 119 ArrayNew 119 ArrayPrepend 119 ArraySet 121 ArraySort 129 AtructKeyArray 129 CreateTimeSpan 35, 228 DateFormat 94 DeleteClientVarialbesList 226 DollarFormat 94 for arrays 124 for queries 34 for structures 133 formatting data 49 GetClientVarialbesList 226 GetException 382, 384 HTMLEditFormat 311, 353 IsAuthenticated 358, 360 IsAuthorized 358, 360, 365 IsCustomFunction 253 IsDefined 47, 92, 129 IsStruct 129 JavaCast 382 ListQualify 86, 87 ListSort 129 MonthAsString 121 Rand 58 RandRange 58 REFind 266 REFindNoCase
266
Reverse 15 StructClear 130 StructCopy 130 StructCount 129 StructDelete 130 StructFind 129 StructInsert 127 StructIsEmpty 129 StructKeyExists 129 StructKeyList 129 StructNew 127 StructUpdate 128 URLEncodedFormat 195 using pound signs 14 WriteOutput 244
cfmodule tag 173, 188 cfoutput tag and pound signs 14 example 12 populating list boxes 82 use with cfquery tag 25 use with component objects 369 cfparam tag 88, 224 testing and setting variables 88 validating data types 90 cfpop tag and queries 34 query results 284 query variables 310 receiving e-mail with 309 using 309 using cfindex with 282 cfquery tag and pound signs 14 creating action pages 105, 110 data sources and 22 populating list boxes 82 syntax 25 using 25 using cfindex with 282 cfqueryparam tag 94 cfrethrow tag 204 CFScript custom function syntax 250 differences from JavaScript 248 example 244 expressions 245 function statement 250 interaction with CFML 249 language 245 reserved words 248 return statement 251 statements 244 var statement 251 cfsearch properties 281 cfsearch tag 270 external attribute 276 cfselect tag handling failed validation 144 passthrough attribute 136 populating list boxes 166 cfset tag and component objects 369 for updating structures 128 using 12 cfslider tag browser considerations 138 description 137
handling failed validaton 144 validating with Javascript 144 cfstoredproce tag, and queries 34 cftextinput tag browser considerations 138 handling failed validaton 144 validating with Javascript 144 CFToken Cooke 222 managing without cookies 222 server-side variable 222 cftree tag browser considerations 138 description 137 form variables 149 handling failed validaton 144 image names 151 URLs in 152 validating with Javascript 144 cftry tag 208 cfupdate tag creating action pages 109 using 109 cfwddx tag 345 CFX tags calling 396 compiling 402 creating in C++ 401 creating in Java 393 debugging in C++ 402 debugging in Java 398 description 390 developing in C++ 401 distributing 405 Java 391 locking 241 locking access to 233, 235 registering 404 sample C++ 401 sample Java 391 tag wizard 401 testing Java 396 CGI and cfhttp Post method 332 returning results to 340 Character classes 261 Check boxes errors 47 lists of values 84 multipe 84 Child tags 180 Class loading Java 395 mechanism 384
410
Index
Class path configuring 391 Java objects and 368 Class reloading, automatifc 395 Classes, debugging 399 Client cookies 222 Client scope 214 Client state management clustering 222 cookies for 222 described 221 enabling 223 Client variables and cflocation tag 226 built-in 225 caching 226 characteristics of 214 configuring 223 creating 224 deleting 226 description 221 exporting from Registry 227 listing 226 setting options for 223 storage 224 storage method 223 using 225 Clustering, client state management 222 Code debugging 236 maintaining 172 protecting 233 reusing 172 validating 194 ColdFusion action pages, extension for 45 application page file extension 7 application pages, about 6 components of 6 description 4 documentation xviii editions of 4 error handling 198 error types 197 features and components 5 integrating e-mail with 302 security features 356 ColdFusion Administrator about 7 creating collectons 273 indexing collections 277 Locking page 236
managing data sources 21 ODBC driver list 21 ColdFusion functions. See CFML Functions ColdFusion Markup Language. See CFML ColdFusion Server about 8 configuring 7 description 7 installing 7 overview 8 ColdFusion site, searching 270 ColdFusion Studio Tag wizard 401 Verity wizard 279 Collections access to 298 creating 273 creating with Administrator 273 creating with cfcollection 274 enabling access to 274 indexing 276 maintenance options 298 managing 298 populating 276 populating from a query 282 searching 270 Columns in tables 19 COM and WDDX 345 connecting to objects 374 description 368 requirements 370 using properties and methods 375 viewing objects 371 COM/DCOM, getting started 370 Commas, in search expressions 288 Comments CFML 16 CFScript 245 HTML 16 Common Object Request Broker Architecture. See CORBA Compiling, C++ CFX tags 402 Component Object Model. See COM Component objects invoking 369 overview 368 Concept operators 295
Conditions, in queries 51 Connections, caching FTP 343 Constructors, using alternate 381 continue, CFScript statement 248 Cookie scope, catching errors 57 Cookies client 222 client state management 221 for storing Client variables 223 managing without 222 sending with cfhttp 337 Copying, server files 326 CORBA calling objects 376 description 368 getting started 376 CreateTimeSpan CFML function 35, 228 Creating action pages 46, 98 action pages to insert data 103 action pages to update data 109 application pages 10 Application.cfm 219 arrays 118 basic graphs 61 client variables 224 collections 273, 274 COM Objects 374 custom CFML tags 174 data grids 153 dynamic form elements 84 error application pages 200 forms with cfform 136 graphs 60 HTML insert forms 102 input forms 97 insert action pages 103, 105 Java CFX tags 393 multidimensional arrays 119 queries from text files 335 queries of queries 34 searchable data sources 273 structures 127 summaries 281 table joins 52 update action pages 109, 110 update forms 106 updateable grids 155 Criteria for searching 51 multiple search 51, 52 Custom exceptions 210 Custom functions
Index
411
arguments 251 calling 251 defining 250 described 250 error handling 256 evaluating strings 255 examples 253 identifying 253 in Application.cfm 254 passing arrays 255 using with queries 254 variables 252 Custom tags ancestor 180 attributes 175 base 180 built-in variables 185 calling 173, 185 CFX 390 children 180 creating 174 data access example 183 data accessibility 181 data exchange 181 descendants 180 distributing 405 downloading 174 encoding 189 encrypting 189 example 178 execution modes 185 filename conflicts 188 installing 187 instance data 185 local 187 location of 173 managing 188 naming 174 nesting 180 parent 180 passing attributes 176, 177 passing data 181 restricting access to 188 scope of 172 shared 187 terminating execution 186 using 173, 174 using existing 174
D
Data accessibility with custom tags 181
converting to JavaScript object 349 exchanging across application servers 347 exchanging with WDDX 345 filtering 51 graphing 62 passing between nested tags 181 selecting for retrieval 40 transferring from browser to server 350 Data sources about 20 adding 22 connecting to 23 LDAP 7 naming 23 native database drivers 7 ODBC 7 OLE-DB 7 specifying dynamically 24 storing Client variables in 223 support for 7 types of 18 understanding 3, 20 Data types about 13 default conversion 382 resolving ambiguous 382 validating 90 Database exceptions 207 Database Management System. See DBMS Databases basics of 19 controlling access to 233 deleting multiple records 113 deleting one record 112 design 3 elements of 19 inserting data into 103 locking 233 retrieving data from 25 updating 106 datasource attribute 25 DateFormat CFML function 94 DBMS 20 Deadlocks 237 Debug information for a query 192 outputting 398 per page 192 Debug settings 192
Debugging C++ CFX tags 402 custom pages and tags 199 full lock checking 236 Java CFX tags 398 Java classes for 399, 400 Declaring arrays 118 structures and sequences 376 Default values, of variables 89 DELETE SQL statement 26, 112 DeleteClientVariablesList CFML function 226 Deleting a database record 112 Client variables 226 data 112 database records 113 e-mail 314 server files 326 structures 130 Delimiters search expression 288 text file 335 Descendant tags 180 Development environment C++ 401 Java 391 Directories indexing 270 information about 329 Directory operations 329 Directory structure, application 216, 217 Displaying query results 30 query results, in tables 49 text 12 variables 12 Distributed data 345 Distributing CFX tags 405 do while loop, CFScript 247 DollarFormat function 94 Drop-down list boxes. See List boxes Dynamic load path 384 Dynamic SQL 96 See also SQL Dynamic SQL parameters 96
E
Editing data in cfgrid tools 10
157
412
Index
Editions of ColdFusion 4 E-mail attachments 313 checking for spooled 308 customizing 306 deleting 314 error logging 308 for multiple recipients 306 form-based 304 handling POP 310 headers 310 indexing 270, 284 integrating Coldfusion 302 multiple recipients 305 query-based 304 receiving 309 sending 302 undelivered 308 Embedding Java applets 167, 169 URLs in a cftree 152 Enabling access to an existing collection 274 Session variables 228 Encoding custom tags 189 Encrypting application pages 358 Error handling ColdFusion 197 custom 215 in custom functions 256 Error messages Administrator settings 192 generating with cferror 199 Error pages custom 199 variables 200 Errors ColdFusion handling of 198 creating application pages 200 custom pages 199 input validation 197, 202 logging 202 Evaluating file upload results 324 strings in functions 255 Evidence operators 290 Example adding a pie chart 72 adding an area graph 74 adding character to a bar graph 69 ancestor data access 183 Application.cfm 220, 364
caching a connection 344 catching security exceptions 361 CFML Java exception handling 383 declaring CORBA structures 377 dynamically linking from a pie chart 77 exception-throwing class 383 graphing a query of queries 63 Java object 385 locking CFX tags 241 multilevel tree control 150 one-level tree control 150 regular expressions 143 request error page 201 restricting file types 322 setting default values 89 setting file attributes 323 synchronizing file system access 241 testing for variables 88 user authentication and authorization 363 using cfauthenticate 359 using cfimpersonate 363 using Java objects 378, 380 using StructInsert 130 using structures 132 validating an e-mail address 144 validation error page 202 variable locking 238 Exception handling CIORBA objects 378 example 208 in ColdFusion 204 Java objects 382 strategies 208 Exceptions custom types 210 database 207 expressions 207 information returned 206 locking 208 missing files 208 naming custom 211 recoverable 205 Exclusive locks about 234 avoiding deadlocks 237 Execution modes 185 ExecutionMode variable 185
Explicit search query expressions 286 Exporting Client variable database 227 Expression exceptions 207 Expressions CFScript 245 search syntax 286 Extending CFML 390
F
Fields, database 19 File operations cfftp actions 344 using cffile 318 using cfftp 341 File scope 185 File types, supported for searching 271 Files controlling type uploaded 321 copying 326 deleting 326 locking access to 235, 241 moving 326 name conflicts 321 naming 16 on server 318 reading 327 renaming 326 types 322 updating 233 uploading 318, 319 writing 328 Find CFML function 260 Finding a strucute key 129 component ProgID and methods 371 similar query results 51 with regular expresions 260 Footers, including 172 for loop, CFScript 246 for-in loop, CFScript 247 Form controls cfform 137 description 41 Form fields, required 91 Form tag syntax 40 Form variables considerations 48 in queries 46 naming 45 processing 45
Index
413
referring to 45 scope of 45, 48 Formatting data items 50 query results 50 Forms about 40 action pages 45 check boxes 84 considerations for 44 creating with cfform 136 deleting data 112 designing 44 drop-down list boxes 166 dynamically populating 82 HTML 40 inserting data 102 Java applets in 167 preserving data 137 requiring entries 89 slider bars 164 text entry boxes 165 tree controls 147 updating data 106 validating data in 91 FROM SQL clause description 27 using 26 FTP actions and attributes 344 chaching connections 343 using cfftp 341 Full lock checking 236 Function variable, definition 251 function, CFScript statement 250 Functions calling 251 definition 47 example custom 253 for arrays 124 IsAuthenticated 360 IsAuthorized 360 JavaScript, for validation 144 structures 133 using pound signs 14 See also ColdFusion functions, Custom functions
382,
384
Graphing individual data points 65 queries 62 query results 63 Graphs appearance attributes 67 bar charts 68 line 74 linking from 77 pie chart appearance 71 types 60 Grids navigating 155 See also cfgrid tag GROUP BY, SQL clause 27
H
Handling applet form variables 169 exceptions 204 failed validation 144 POP Mail 310 Headers, including 172 Hidden fields 91 Horizontal bar charts 68 HTML and ColdFusion 10 knowing 3 using tables 49 using with cfform 136 HTMLEditFormat CFML function 311, 353 HTTP/URL problems 195
methods 277 query results 270 summary of 279 Web sites 270 Indexing collections about 276 with Administrator 277 with cfindex 278 Infix notation, search string 287 Input validation cftree 149 error type 197 with cfform Controls 139 with JavaScript 144 INSERT SQL statement 26 Inserting data description 102 with cfinsert 103 with cfquery 105 Installing Custom Tags 187 Instance data, custom tag 185 International Languages, search support 272 Invoking COM methods 375 component objects 369 methods in cfobject 375 IsAuthenticated CFML function 358, 360 IsAuthorized CFML function 358, 360, 365 IsCustomFunction CFML function 253 IsDefined CFML function 47, 92,
129
IsStruct CFML function
129
I
if-else, CFScript statements 246 Impersonating, with cfimpersonate 362 Implementing C++ CFX tags 402 Dynamic SQL 96 Java CFX tags 393 Importing C++ CFX tags 406 Java CFX tags 406 IN SQL operator 27 Indexing cfldap query results 283 database query results 282 directories 270 e-mail 270, 284 external Verity collections 276
J
Java and ColdFusion data 381 and WDDX 345 class loading mechanism 384 class reloading 395 customizing and configuring 392 development enviroment 391 getting started 378 object example 385 Java applets embedding 167, 169 form variables 169 overriding default values 169 registering 167 Java CFX tags
G
Generated content 187 Get method, cfhttp 332 GetClientVariablesList CFML function 226
414
Index
class loading 395 debugging 398, 399 example 397 importing 406 life cycle of 396 writing 393 Java objects calling 378 considerations 380 exception handling 382 JavaCast CFML function 382 JavaScript differences from CFScript 248 validating with 144 Joining tables 52
132
M
Mail servers, and ColdFusion 302 Managing client state 221 client state, in clusters 222 client state, without cookies 222 collections 298 custom tags 188 Mapping, application framework 216 Matches, pattern 142 method attribute, cfhttp tag 332,
337
K
Keys, listing structure
129
L
LDAP query results 283 LIKE SQL operator 27, 51 Line graphs, setting appearance 74 Linking from graphs 77 List boxes populating 166 populating dynamically 82 Listing Applicaton variables 231 Client variables 226 Session variables 230 ListQualify CFML function 86, 87 ListSort CFML function 129 Loading, Java CFX classes 395 Local tags 187 Locking automatic 236 avoiding deadlocks 237 CFX tags 241 exceptions 208 file access 241 scopes 234 with cflock 233 Locks automatic checking of 236 controlling time-outs 235 exclusive 234 full checking 236 naming 235 read-only 234 scopes and names 234 types 234 Logging errors 202
Methods, calling 369 Missing files, exceptions 208 Modes of execution 185 Modifiers, searching 297 MonthAsString CFML function 121 Moving data across the Web 345 server files 326 Multicharacter regular expressions for searching 263 for validation 141 Multiple selection lists 86 Multiple tables, searching 52
query 394 Request 393 Response 393 using properties 369 ODBC configuration problems 195 data sources 7 described 20 UNIX drivers 21 Windows drivers 20 OLE/COM Object Viewer 371 OLE-DB, data sources 7 OnRequestEnd.cfm 216 Open Database Connectivity. See ODBC Operators concept 295 core 296 evidence 290 proximity 291 relational 292 search 290 SQL 27 Optional arguments 251 OR SQL operator 27 ORDER BY SQL clause 27 Outputting debug information 398 query data 30 Overriding default Java applet values 169
N
name cfquery attribute 25 Naming applications 219 variables 179 Naming conventions, for custom exceptions 211 Navigating grids 155 Nested tags, using Request scope 174 Nesting cflock tags 237 cfloops for arrays 122 custom tags 180 object calls 370 NOT SQL operator 27
P
Parameters, dynamic SQL 96 Parent tags 180 Passing arguments 252 arrays to custom functions 255 custom tag attributes 176, 177 custom Tag data 181 passthrough attribute 136 Pattern matching 51 Performing a query on a query 35 Perl 345 Pie charts, setting appearance 71 POP 7 Populating arrays from queries 123 arrays with ArraySet 121 arrays with cfloop 121 arrays with nested loops 122 collections 276 grids from queries 154 POSIX character classes 262
O
Objects calling methods 369 calling nested 370 COM 368 Java 368
Index
415
Post cfhttp method 332, 337 Pound signs, using 14 Precedence rules, search 287 Prefix notation, search strings 287 preservedata cfform attribute 137 Problems, troubleshooting 195 Processing Application.cfm 216 form variables on action pages 45 Java CFX requests 393 OnRequestEnd.cfm 216 Protecting data 233 Proximity operators 291 Punctuation, searching 289 Python 345
indexing 270, 282 layout 49 LDAP 283 no records 55 records returned 32 returning 55 returning incrementally variables 32 Quotes for IsDefined CFML function 48 using 26, 48
56
R
Rand CFML function 58 RandRange CFML function 58 Reading, a text file 327 Read-only locks 234 Receiving e-mail 309 Records definition 19 returned 55 Recoverable expressions 205 Referencing array elements 119 REFind CFML function 266 REFindNoCase CFML function 266 Registering CFX tags 404 COM objects 371 Java applets 167 Registry exporting Client variables 227 storing Client variables 223 Regular expressions anchoring to search string 264 backreferences 142, 265 character classes 261 common uses 267 examples 143, 267 finding repeated words 265 for form validaton 140 for searching and replacing text 259 multicharacter 263 partial matches 142 replacing with 260 returning matched subexpressions 266 single-character 140, 261 Relational databases 3 Relational operators 292 Remote Development Services Security 356
Q
Queries as function parameters 254 building 26, 28 building graphically 26 creating from text files 335 graphing 62 grouping output 148 guidelines for creating 29 guidelines for outputting 31 joining tables 52 multiple conditions 51 outputting 30 using form variables 46 using query results in 34 validating 94 Queries of queries about 34 creating 34 performing 35 Query CFX object 394 Query expressions explicit search 286 search 285 simple search 285 Query functions 34 Query objects 25, 394 Query parameters, checking 94 Query properties, guidelines for 33 Query results about 32 cfpop 284 columns in 32 current row 32 displaying 30 graphing 63
Renaming server files 326 Replace CFML function 260 Replacing using regular expressions 260 Request object 393, 394 Request scope 174 Requirements for COM 370 Requiring form entries 89 Reserved words, CFScript 248 Reset buttons 42 Resolving ambiguous data types 382 custom tag file conflicts 188 filename conflicts 321 Resources COM 368 CORBA 368 regular expressions 143 Response object 393, 394 Results, returning incrementally 56 Retrieving binary files 332 e-mail attachments 313 e-mail headers 310 e-mail messages 312 files 341 query data 25 text 332 return CFScript statement 251 Returning file information 329 query results 55 results incrementally 56 subexpressions 266 Reusing code cfinclude 172 custom tags 173 techniques for 172 Reverse CFML function 15 Rows in tables 19 Runtime validation 194
S
Sample CFX tags C++ 401 Java 391 Saving application pages 11 binary files 334 Web pages 333 Scope of custom tags 172 of Form variables 48
416
Index
Scopes and custom functions 252 Application 215, 230 Attributes 174, 176 Caller 174, 176 Client 214, 221, 223 File 185 Form 14, 45 local 14 locking 234 managing locking of 237 Request 174 Server 215, 232 Session 214, 221, 228 types 13 URL 14 Variables 14 Variables, and custom tags 172 Score search operators 296 Search and replace 260 Search criteria database retrieval 51 example of 98 multiple 52 Search expressions commas in 288 composing 287 delimiters 288 document fields 294 Search expressions, evidence operators 290 Search interfaces, building 279 Searching a ColdFusion Web Site 270 collections 270 creating index summaries 281 criteria for 51 explicit expressions 286 explicit syntax 286 expression syntax 286 external verity collections 276 file types 271 full-text 270 international languages 272 modifiers 297 multiple tables 52 numeric values 84, 86 operators 290 prefix and infix notation 287 punctuation 289 results of 281 special characters 287, 289 special characters as literals 289
string values 85, 87 SUBSTRING operator 294 wildcards as literals 289 with wildcards 288 Securing a collection 298 custom tags 188 Security application security 355 Application.cfm example 364 authenticating users 360 authentication example 363 authorization example 363 authorizing users 360 catching exceptions 361 cfauthenticate tag 360 cfimpersonate Tag 362 encrypting strings 358 implementing 358 IsAuthenticated CFML function 360 IsAuthorized CFML function 360 IsAuthorized example 365 overview 357 Web server 215 SELECT SQL statement 26 Selecting an indexing method 277 Selection lists, multiple 86 Sending e-mail 302, 303 e-mail to multiple recipients 305 form-based e-mail 304 mail as HTML 308 query-based e-mail 304 Serialization 347 Server scope 215 Server variables 215 built-in 232 using 232 Servers remote 332, 341 retrieving files from 332 uploading files 319 Session scope 214 Session variables 214, 221, 229 built-in 229 enabling 228 listing 230 using 228 Session, definition of 228 setCookie attribute 359 Setting
application defaults 219 bar chart characteristics 68 Client variable options 223 COM properties 375 file and directory attributes 323 line graph characteristics 74 pie chart characteristics 71 properties 375 Setting up C++ development environment 401 Java development environment 391 Settings, application-level 214 Shared tags 187 Simple query expressions 285 Simple syntax 286 Single quotes, in SQL 26, 87 Single-character regular expressions 140, 261 Single-threading sessions 237 Slider bar controls 164 SMTP 302 Special characters 140, 287, 289 Specifying a connection string 23 client variable storage 224 data sources dynamically 24 execution modes 185 tree items in URLs 153 SQL AVG function 65 DELETE Statement 112 dynamic 96, 99 generating dynamically 45 guidelines 27 INSERT statement 105 LIKE operator 51 non-standard 28 operators 27 single quotes in 26, 87 statement clauses 27 statements 26 SUM function 73 syntax elements 26 text literals in 26 UPDATE statement 106 Use in cfquery 25 WHERE clause 45 writing 26 Standard variables. See Built-in variables Statement clauses, SQL 27 Statements
Index
417
CFScript 244, 245 SQL 26 Strings evaluating in functions 255 limiting size of 264 storing complex data in 353 StructClear CFML function 130 StructCopy CFML function 130 StructCount CFML function 129 StructDelete CFML function 130 StructFind CFML function 129 StructInsert CFML function 127 StructIsEmpty CFML function 129 StructKeyArray CFML function 129 StructKeyExists CFML function 129 StructKeyList CFML function 129 StructNew CFML function 127 StructUpdate CFML function 128 Structured Query Language. See SQL Structures about 125 adding data to 127 copying 130 creating 127 custom tag 177 deleting 130 example 130 finding keys 129 functions 133 getting information on 129 listing keys in 129 looping through 132 notation for 126 passing tag arguments 177 sorting keys 129 updating 128 sub tags associating with the base tag 180 definition 180 Submit buttons 42 SUBSTRING Search operator 294 SUM SQL function 73 Summaries, search 281 switch-case,CFScript 247
expression
286
T
Tables displaying queries 49 using HTML 49 Tag Wizard, using 401 Tags, context information 206 Testing a variables existence 47 query parameters 94 Text control 41 Text files column headings 335 creating queries from 335 delimiters 335 Text, displaying 12 throwOnTimeout, cflock attribute 235 Time zone processing, WDDX 347 time-out attribute, cflock 235 Transferring data, from browser to server 350 cftree tag See also Tree controls Tree controls, structuring 150 Troubleshooting 195
User edits, returning 156 User-defined functions. See Custom functions Users, keeping track of 221
V
Validating at runtime 194 code 194 data types 90 form attributes 139 form field data types 91 form input 149 JavaScript functions 144 queries 94 user input 91 using regular expressions 140 Validation, error handling 144 var, CFScript statement 251 Variables about 13 Application 230 Application scope 215, 230 application-level 216 Attributes scopes 174 caching 226 Caller scope 174 CfScript 245 Client scope 214, 221 configuring Client 223 default 88, 89, 219 defining 12 displaying 12, 14 ensuring existence of 88 evaluating 215 Form 14, 45 formatting 50 forms 40 in Custom functions 252 local 14 locking example 238 naming 179 passing 332 processing 40 Request scope 174 scope of 13 scopes for custom pages 174 sending 337 Server 232 Server scope 215 Session scope 214, 221, 228,
U
UNIX C++ debuggers 403 permissions 323 Updating a database with cfgridupdate 159 a database with cfquery 160 a structure with cfset 128 a structure with StructUpdate 128 data using forms 106 files 233 values in structures 128 Uploading files 319 Uploads, contolling file type 321 URLEncodedFormat CFML function 195 URLs, specifying links from graphs 77 User authentication cfauthenticate tag 359 cfimpersonate tag 362 example 364 IsAuthenticated CFML function 360
229
setting default values 89 testing for existence 47, 88
195
418
Index
types of 13 URL 14 using pound signs 14 validating 91 See also Scope, Built-in variables Verbs, SQL 26 Verity about 270 See also Searching, Search expressions Verity wizard 279 Viewing application pages 11 online documentation xix
Windows file attributes 323 Windows NT, debugging C++ CFX tags 402 Wizards Tag 401 Verity 279 WriteOutput CFML function 244
X
XML, and WDDX
345
W
WDDX and application-level data 347 and Web Services 346 components 346 converting CFML to JavaScript 349 exchanging data 347 operation of 348 purpose of 345 storing data in strings 353 time zone processing 347 transferring data 350 Web accessing with cfhttp 332 application framework 214 overview of distributed data 345 Web Distributed Data Exchange. See WDDX Web pages dynamic 18 saving 333 static 18 Web root directory 11 IP address of 11 localhost 11 Web server security 215 Web sites indexing 270 searching 270 WHERE SQL clause comparing with 45 description 27 while loop, CFScript 246 Wildcards in searches 288 in SQL 51