Using the Request Scope

an article added by: Greg Hunter at 04052008


Programming :: Using the Request Scope ::

 French | Spanish | Portuguese | Italian | German | Japanese | Chinese | Korean | Russian | Arabic Bookmark and Share

Variables within custom tags exist in their own variable space, and the only way to share data back and forth between the calling page and the custom tag is by using the Attributes and Caller scopes. Request variables are available to all templates in a request, including custom tags, and are the best way to give custom tags access to global variables such as Request.MainDSN, Request.Username, and Request.Password. You should generally restrict your use of Request-scope variables in your custom tags to global constants such as these. All other data needed by a custom tag should be passed to it via attributes. As can functions, custom tags can be called recursively. This is rare, however, and usually on an advanced scale, because recursion in custom tags is used differently than in user-defined functions. Because UDFs are more suited to making calculations, you find more numeric recursion in UDFs. On the other hand, recursion in custom tags is best suited for such procedures as recursing over structures or directory hierarchies, where the purpose is page output rather than returning single results from each recursive call. The code shows a custom tag that takes a directory path and returns a listing of all the files and subfolders of that path. It uses recursion to list the contents of subdirectories as well.

<cfparam name=”Attributes.Directory”>
   <cfoutput>
   #Attributes.Directory#\<br>
   </cfoutput>
   <cfdirectory action=”LIST”
   directory=”#Attributes.Directory#”
   name=”GetFiles”>
   <cfloop query=”GetFiles”>
   <cfif GetFiles.Type EQ “Dir”>
   <cfif GetFiles.Name NEQ “.” AND GetFiles.Name NEQ “..”>
   <cf_ListDir
   directory=”#Attributes.Directory#\#GetFiles.Name#”>
   </cfif>
   <cfelse>
   <cfoutput>
   #Attributes.Directory#\#GetFiles.Name#<br>
   </cfoutput>
   </cfif>
 </cfloop>

The CFIF test for “GetFiles.Name NEQ “.” AND GetFiles.Name NEQ “..”” is not necessary in ColdFusion MX, because MX no longer returns these values. We kept the test in this listing for backward compatibility with ColdFusion 5. ListDir.cfm uses CFDIRECTORY to get all of the files and subfolders of the directory passed to the tag. It then loops over the list of files and directories and outputs every file that it finds. Whenever the loop encounters a directory, ListDir.cfm calls itself recursively, passing the name of the new directory. We called ListDir.cfm on our systems by using the following:

<cf_ListDir Directory=”C:\inetpub\wwwroot\BibleExample”>

CFABORT is mentioned as a way to immediately stop a request’s execution. Inside a custom tag, you rarely want to end an entire request, but you may want to end the execution of the tag and return to the calling page. A call to CFEXIT looks as follows:

<cfexit method=”ExitTag”>

You have the following three possible values for method:

ExitTag: Resumes execution after the closing tag.

ExitTemplate: Resumes execution after either the opening or closing tag, depending on where it’s called.

Loop: Re-executes the body of the custom tag.

ExitTag stops the current tag, meaning that execution continues after the closing tag (or the opening tag if you have no closing tag). The codes show a custom tag and its calling page.

<cf_MyTag>
   This is the tag content.
   </cf_MyTag>
 This is content after the closing tag.
<cfif ThisTag.ExecutionMode EQ “Start”>
   This is the opening tag content.
   <cfexit method=”ExitTag”>
   This is content after the CFEXIT call.
   <cfelse>
   This is the closing tag content.
 </cfif>

Running MyTagCall.cfm produces the following:

This is the opening tag content.
   This is content after the closing tag.

Calling CFEXIT immediately skips past the closing tag, so ColdFusion skips all the extra output in the tag and calling page. ExitTemplate is similar to ExitTag; in fact, it’s different only if you call it in the Start mode. Instead of exiting the tag, ExitTag skips past the end of the current template; in other words, calling ExitTemplate in the Start mode immediately begins executing the tag body. On the other hand, calling ExitTemplate in the End mode immediately ends the custom tag.

<cfif ThisTag.ExecutionMode EQ “Start”>
   This is the opening tag content.
   <cfexit method=”ExitTemplate”>
   This is content after the CFEXIT call.
   <cfelse>
   This is the closing tag content.
 </cfif>

Calling the code now shows the following output:

This is the opening tag content.
   This is the tag content.
   This is the closing tag content.
   This is content after the closing tag.

ExitTemplate skips the end of the Start mode, but continues execution at the beginning of the body. Loop is very different from ExitTag and ExitTemplate because Loop executes code that’s already run. Rather than skipping past part of the tag, Loop re-executes the body of the custom tag. As such, it can be called only in the End mode of the custom tag. Loop is used much less often than ExitTag or ExitTemplate and is almost exclusively used with nested tags. The changes to these two tags require a change in the tag’s architecture. In the codes, OutputTable.cfm did most of the work, and OutputColumn.cfm just defined the columns to select from the database and output the header row for the listing. The modifications that you’re going to make in the following listings make OutputTable.cfm get the data from the database, but the work of outputting the data mostly falls on OutputColumn.cfm, which is a better division of labor. The codes show the modifications to OutputTable.cfm and OutputColumn.cfm.

<cfparam name=”Attributes.TableName”>
   <cfif ThisTag.ExecutionMode EQ “Start”>
   <table>
   <tr>
   <!--- Request.RowNumber contains the current row index of the
   query. I start this value at zero, meaning that OutputColumn should put
   out the header row. --->
   <cfset Request.RowNumber = 0>
   <cfelse>
   <!--- The first thing I need to do in the closing tag is put out
   the ending TR for the current row. --->
   </tr>
   <!--- I only want to perform the query once, so I check to see that
   it was the header row that was just output. --->
   <cfif Request.RowNumber EQ 0>
   <!--- I dynamically build this query based on the contents of
   ThisTag.AssocAttribs. --->
   <cfquery name=”Request.GetData”
   datasource=”#Request.MainDSN#”>
   SELECT
   <cfloop
   from=”1”
   to=”#ArrayLen(ThisTag.AssocAttribs)#”
   index=”i”>
   #ThisTag.AssocAttribs[i].ColumnName#
   <cfif i LT ArrayLen(ThisTag.AssocAttribs)>,</cfif>
 </cfloop>
FROM
   #Attributes.TableName#
   </cfquery>
   </cfif>
   <!--- I increment the current row number --->
   <cfset Request.RowNumber = Request.RowNumber + 1>
   <!--- If the new row number is still within the query’s record
   count, I begin a new table row and use CFEXIT Loop to re-execute the
   body of the custom tag, meaning that the calls to CF_OutputColumn will
   be re-run. --->
   <cfif Request.RowNumber LTE Request.GetData.RecordCount>
   <tr>
   <cfexit method=”Loop”>
   </cfif>
   </table>
 </cfif>
<cfparam name=”Attributes.ColumnName”>
   <cfparam name=”Attributes.Label” default=”#Attributes.ColumnName#”>
   <cfassociate basetag=”CF_OUTPUTTABLE”>
   <cfset ParentData = GetBaseTagData(“CF_OUTPUTTABLE”)>
   <!--- I must check to see which row to output. If Request.RowNumber is
   zero, the query hasn’t been run yet, so I output the header row.
   Otherwise, I put out the value of the current cell in the
   Request.GetData query. --->
   <cfoutput>
   <cfif Request.RowNumber EQ 0>
   <td bgcolor=”#ParentData.Attributes.HeaderRowColor#”>
   <b>#Attributes.Label#</b>
   </td>
   <cfelse>
   <td>
   #Request.GetData[Attributes.ColumnName][Request.RowNumber]#
   </td>
   </cfif>
 </cfoutput>

Notice how these listings are using Request variables? You use Request variables to communicate back and forth between the parent tag’s End mode and the nested child tags, which is another acceptable use of them. You can also do this by using CFASSOCIATE and GetBaseTagData(), but doing so would be more complicated.

legal disclaimer

Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.

related articles

1. Building the company edit action template
The code in CompanyEditAction.cfm is like the code in CompanyAddAction.cfm, but the edit action updates rather than inserts. Create a file named CompanyEditAction.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <cfquery name=”UpdateCompany” datasource=”#Request.MainDSN#”> UPDATE Company SET CompanyName = ‘#Trim(Form.CompanyName)#’, Address = ‘#Trim(Form.Address)#’, City = ‘#Trim(Form.City)...

2. Adding a New Employee to the Database
The CFQUERY in CompanyDeleteAction.cfm uses a DELETE statement with two SQL clauses: DELETE and WHERE. DELETE tells the database the table from which to delete a record, and WHERE tells the database which record to delete. You can watch the company delete process in action. Point your Web browser to http://<yourserver>/CFMXBible/Ch02/CompanyGetDeleteForm.cfm and enter a CompanyID. (To get a valid ID, go to the company list and pick a number from the ID column.) Click Submit to see the chosen company’s informatio...

3. Modifying an Employee in the Database
The DateFormat() function around the DateOfBirth column in the codereturns the employee’s birth date reformatted according to a display mask. DateOfBirth normally comes back from the database in the following format: 2002-01-01 00:00:00.0 That format is not very user-friendly. Calling DateFormat() with a mask of “mm/dd/yyyy” returns the date as follows: 01/01/2002 This version is, of course, more natural and easy to read. The same is true for the employee edit process...

4. Removing an Employee From the Database
The user must have the capability to remove employees from the database. The employee delete process is a simple combination of techniques that you have already learned, such as retrieving a record from the database, displaying that record in a template, and so on. The first page in this process is nearly identical to the employee get edit form. Create a file named EmployeeGetDeleteForm.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <html> <head> <ti...

5. Making direct links to the forms
Say that you want to modify or delete a company. Right now, you need to remember the company’s ID, go back to the launch pad, click Company Edit, and enter the company ID, all just to get to the edit form. Wouldn’t you rather click a company in the list and go directly to the edit form? ... <table> <tr> <td><b>ID</b></td> <td><b>Name</b></td> <td><b>Address</b></td> <td><b>City</b></t...

6. Using a Custom Tag
Custom tags are reusable, developer-authored extensions to the ColdFusion language. The custom tag that you create in the following parts displays today’s date in a familiar format. Create a file named TodaysDate.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <cfoutput>#DateFormat(Now(), “ddd, mmm d, yyyy”)#</cfoutput> Now() returns the current date and time, and DateFormat() reformats the date. To call your custom tag, open index.cfm, a...

7. Creating your physical data model
Physical data models are extracted from their logical counterparts by mapping logical objects to physical objects supported by the target database platform. The following table shows the relationship between logical and physical objects. In many cases, your physical data model almost mirrors your logical data model because entities typically map directly to the tables that store them. Exceptions to this rule are logical data models that contain nonspecific relationships and entity subtypes. Although entity subtypes are an advanced top...

8. Understanding All Relational Result Sets
This article can help you better understand complicated SQL containing multitable joins, group-related clauses, and aggregate functions—by far the most problematic topics for most database developers. You also learn the correct way to handle database exceptions and incorporate them as actual functionality in your ColdFusion application. You learn, too, how to increase performance by caching queries in memory for fast access. You can memorize SQL clauses and Bachus-Naur forms until you’re blue in the face, ...

9. How and when to use Group by Having and Distinct
After learning how SQL works internally, you can better learn how to put the more complicated aspects of it to use. First we need to clarify the difference between GROUP BY and DISTINCT. Quite a bit of confusion exists over these two clauses, because they often produce the same query results but for very different reasons. In fact, GROUP BY and DISTINCT are not related in any way whatsoever. The GROUP BY clause produces as its intermediate work product a table of rows representing each group, and a sort of “invisible third dimen...