Using Client Variables


Client variables are similar to cookies, except that they are stored on the server, rather than on the client (browser) machine. In many situations, you can use the two almost interchangeably. You're already familiar with cookies, so learning how to use client variables will be a snap. Instead of using the COOKIE prefix before a variable name, you simply use the CLIENT prefix.

Okay, there's a little bit more to it than that, but not much.

NOTE

Before you can use the CLIENT prefix, you must enable ColdFusion's Client Management feature. See the section "Enabling Client Variables," later in this chapter.


NOTE

It's worth noting that client variables can also be configured so that they are stored on the browser machine, if you take special steps in the ColdFusion Administrator. They then become essentially equivalent to cookies. See the section "Adjusting How Client Variables Are Stored," later in this chapter.


How Do Client Variables Work?

Client variables work like this:

1.

The first time a particular user visits your site, ColdFusion generates a unique ID number to identify the user's browser.

2.

ColdFusion sets this ID number as a cookie called CFID on the user's browser. From that point on, the browser identifies itself to ColdFusion by presenting this ID.

3.

When you set a client variable in your code, ColdFusion stores the value for you on the server side, without sending anything to the browser machine. It stores the CFID number along with the variable, to keep them associated internally.

4.

Later, when you access or output the variable, ColdFusion simply retrieves the value based on the variable name and the CFID number.

For the most part, this process is hidden to you as a developer. You simply use the CLIENT scope prefix in your code; ColdFusion takes care of the rest.

Enabling Client Variables

Before you can use client variables in your code, you must enable them using an Application.cfc file. In the last chapter, you learned how to use this file to enable application variables. You can modify the behavior of the application using This-scope variables. Table 20.3 lists values relevant to client variables.

Table 20.3. Additional Application.cfc This-Scope Values Relevant to Client Variables

ATTRIBUTE

DESCRIPTION

name

Optional. A name for your application. For more information about the NAME attribute, see the section "Enabling Application Variables" in the last chapter, "Introducing the Web Application Framework."

clientManagement

Yes or No. Setting this value to Yes enables client variables for the application.

clientStorage

Optional. You can set this attribute to the word Registry, which means the actual client variables will be stored in the Registry (on Windows servers). You can also provide a data source name, which will cause the variables to be stored in a database. If you omit this attribute, it defaults to Registry unless you have changed the default in the ColdFusion Administrator. For details, see "Adjusting How Client Variables Are Stored," later. Another option is Cookie, which tells ColdFusion to store the client variables as cookies on the user's browser.

setClientCookies

Optional. The default is Yes, which allows ColdFusion to automatically set the CFID cookie on each browser, which it uses to track client variables properly for each browser. You can set this value to No if you don't want the cookies to be set. But if you do so, you will need to do a bit of extra work. For details, see "Adjusting How Client Variables Are Stored," later.

setDomainCookies

Optional. The default is No, which tells ColdFusion to set the CFID cookie so that it is visible only to the current server. If you have several ColdFusion servers operating in a cluster together, you can set this to Yes to share client variables between all your ColdFusion servers. For details, see "Adjusting How Client Variables Are Stored," later.


For now, just concentrate on the clientManagement attribute (the others are discussed later). Listing 20.5 shows how easy it is to enable client variables for your application. After you save this code in the Application.cfc file for your application, you can start using client variables. (Be sure to save Listing 20.5 as Application.cfc, not Application2.cfc.)

NOTE

If you attempt to use client variables without enabling them first, an error message will be displayed.


Listing 20.5. Application2.cfcEnabling Client Variables in Application.cfc
 <!---  Filename: Application.cfc  Created by: Raymond Camden (ray@camdenfamily.com)  Handles application events. ---> <cfcomponent output="false">   <cfset this.name="OrangeWhipSite">   <cfset this.clientManagement=true> </cfcomponent> 

Client variables are ideal for storing things like user preferences, recent form entries, and other types of values that you don't want to force your users to provide over and over again.

Remembering Values for Next Time

Consider a typical search form, in which the user types what they are looking for and then submits the form to see the search results. It might be nice if the form could remember what the user's last search was.

The code in Listing 20.6 lets it do just that. The basic idea is that the form's search criteria field will already be filled in, using the value of a variable called SearchPreFill. The value of this variable is set at the top of the page and will be set to the last search the user ran, if available. If no last search information exists (if this is the first time the user has used this page), it will be blank.

Listing 20.6. SearchForm1.cfmUsing Client Variables to Remember the User's Last Search
 <!---  Filename: SearchForm1.cfm  Created by: Nate Weiss (NMW)  Please Note Maintains "last" search via Client variables ---> <!--- Determine value for "Search Prefill" feature ---> <!--- When user submits form, save search criteria in client variable ---> <cfif isDefined("FORM.searchCriteria")>  <cfset CLIENT.lastSearch = FORM.searchCriteria>  <cfset searchPreFill = FORM.searchCriteria> <!--- If not submitting yet, get prior search word (if possible) ---> <cfelseif isDefined("CLIENT.lastSearch")>  <CFSET searchPreFill = CLIENT.lastSearch> <!--- If no prior search criteria exists, just show empty string ---> <cfelse>  <cfset searchPreFill = ""> </cfif> <html> <head><title>Search Orange Whip</title></head> <body>  <h2>Search Orange Whip</h2>  <!--- Simple search form, which submits back to this page --->  <cfform action="#cgi.script_name#" method="post">  <!--- "Search Criteria" field --->  Search For:  <cfinput name="SearchCriteria" value="#searchPreFill#"  required="Yes"  message="You must type something to search for!">  <!--- Submit button --->  <input type="submit" value="Search"><br>  </cfform> </body> </html> 

The first part of this template (the <cfif> part) does most of the work because it's in charge of setting the searchPreFill variable that provides the "last search" memory for the user. There are three different conditions to deal with. If the user currently is submitting the form to run the search, their search criteria should be saved in a client variable called CLIENT.lastSearch. If the user isn't currently submitting the form but has run a search in the past, their last search criteria should be retrieved from the lastSearch client variable. If no last search is available, the isDefined("CLIENT.lastSearch") test will fail, and searchPreFill should just be set to an empty string.

The rest of the code is an ordinary form. Note, though, that the value of the searchPreFill variable is passed to the <cfinput> tag, which presents the user with the search field.

If you visit this page in your browser for the first time, the search field will be blank. To test the use of client variables, type a word or two to search for and submit the form. Of course, no actual search takes place because no database code yet exists in the example, but the form should correctly remember the search criteria you typed. You can close the browser and reopen it, and the value should still be there.

NOTE

Assuming that you haven't changed anything in the ColdFusion Administrator to the contrary, the value of CLIENT. LastSearch will continue to be remembered until the user is away from the site for 90 days.


Using Several Client Variables Together

No limit is set on the number of client variables you can use. Listing 20.7 builds on the search form from Listing 20.6, this time allowing the user to specify the number of records the search should return. A second client variable, called lastMaxRows, remembers the value, using the same simple <cfif> logic shown in the previous listing.

Listing 20.7. SearchForm2.cfmUsing Client Variables to Remember Search Preferences
 <!---  Filename: SearchForm2.cfm  Created by: Nate Weiss (NMW)  Please Note Maintains "last" search via Client variables ---> <!---   When user submits form, save search criteria in Client variable ---> <cfif isDefined("FORM.searchCriteria")>  <cfset CLIENT.lastSearch = FORM.searchCriteria>  <cfset CLIENT.lastMaxRows = FORM.searchMaxRows> <!--- if not submitting yet, get prior search word (if possible) ---> <cfelseif isDefined("CLIENT.lastSearch") and           isDefined("CLIENT.lastMaxRows")>  <cfset searchCriteria = CLIENT.lastSearch>  <cfset searchMaxRows = CLIENT.lastMaxRows> <!--- if no prior search criteria exists, just show empty string ---> <cfelse>  <cfset searchCriteria = "">  <cfset searchMaxRows = 10> </cfif> <html> <head><title>Search Orange Whip</title></head> <body> <h2>Search Orange Whip</h2> <!--- Simple search form, which submits back to this page ---> <cfform action="#cgi.script_name#" method="post"> <!--- "Search Criteria" field ---> Search For: <cfinput name="SearchCriteria" value="#searchCriteria#" required="Yes" message="You must type something to search for!"> <!--- Submit button ---> <input type="Submit" value="Search"><br> <!--- "Max Matches" field ---> <i>show up to <cfinput name="SearchMaxRows" value="#searchMaxRows#" size="2" required="Yes" validate="integer" range="1,500" message="Provide a number from 1-500 for search maximum."> matches</i><br> </cfform> <!--- If we have something to search for, do it now ---> <cfif searchCriteria neq "">   <!--- Get matching film entries from database --->   <cfquery name="getMatches" datasource="ows">   SELECT FilmID, MovieTitle, Summary   FROM Films   WHERE MovieTitle LIKE '%#SearchCriteria#%'   OR Summary LIKE '%#SearchCriteria#%'   ORDER BY MovieTitle   </cfquery>   <!--- Show number of matches --->   <cfoutput>   <hr><i>#getMatches.recordCount# records found for   "#searchCriteria#"</i><br>   </cfoutput>   <!--- Show matches, up to maximum number of rows --->   <cfoutput query="getMatches" maxrows="#searchMaxRows#">   <p><b>#MovieTitle#</b><br>   #Summary#<br>   </cfoutput> </cfif> </body> </html> 

Next, the actual search is performed, using simple LIKE code in a <cfquery> tag. When the results are output, the user's maximum records preference is provided to the <cfoutput> tag's maxrows attribute. Any rows beyond the preferred maximum aren't shown. (If you want to brush up on the <cfquery> and <cfoutput> code used here, see Chapter 10, "Creating Data-Driven Pages.")

Not only does this version of the template remember the user's last search criteria, but it also actually reruns the user's last query before they even submit the form. This means the user's last search results will be redisplayed each time they visit the page, making the search results appear to be persistent. The results are shown in Figure 20.3.

Figure 20.3. Client variables make maintaining the state of a user's recent activity easy.


You easily could change this behavior by changing the second <cfif> test to isDefined("FORM. SearchCriteria"). The last search would still appear prefilled in the search form, but the search itself wouldn't be rerun until the user clicked the Search button. Use client variables in whatever way makes sense for your application.

TIP

To improve performance, you could add a cachedwithin or cachedafter attribute to the <cfquery> tag, which enables ColdFusion to deliver any repeat searches directly from the server's RAM memory.


For details, see Chapter 25, "Improving Performance."


Deleting Client Variables

Once set, client variables are stored semi-permanently: they're deleted only if a user's browser doesn't return to your site for 90 days. In the next section, you learn how to adjust the number of days that the variables are kept, but sometimes you will need to delete a client variable programmatically.

NOTE

It's important to understand that a client doesn't have its own expiration date. Client variables don't expire individually; the whole client record is what expires. So, it's not that a client variable is deleted 90 days after it is set. Rather, the client variable (and all other client variables assigned to the user's machine) is deleted after the user lets 90 days pass before revisiting any pages in the application. For more information about tweaking the expiration system, see "Adjusting How Long Client Variables Are Kept," in the next section.


ColdFusion provides a deleteClientVariable() function, which enables you to delete individual client variables by name. The function takes one argument: the name of the client variable you want to delete (the name isn't case sensitive). Another handy housekeeping feature is the getClientVariablesList() function, which returns a comma-separated list of the client-variable names that have been set for the current browser.

Listing 20.8 shows how these two functions can be used together to delete all client variables that have been set for a user's browser. You could use code such as this on a start-over type of page, or if the user has chosen to log out of a special area.

Listing 20.8. DeleteClientVars.cfm Deleting Client Variables Set for the Current Browser
 <!---  Filename: DeleteClientVars.cfm  Created by: Nate Weiss (NMW)  Purpose: Deletes all client variables associated with browser ---> <html> <head><title>Clearing Your Preferences</title></head> <body> <h2>Clearing Your Preferences</h2> <!--- For each client-variable set for this browser... ---> <cfloop list="#getClientVariablesList()#" index="thisVarName">  <!--- Go ahead and delete the client variable! --->  <cfset deleteClientVariable(thisVarName)>  <cfoutput>#thisVarName# deleted.<br></cfoutput> </cfloop> <p>Your preferences have been cleared.</p> </body> </html> 

Along with deleteClientVariable(), you can also treat the CLIENT scope like a structure. So for example, you can remove the client variable name using structDelete(CLIENT,"name").

Adjusting How Client Variables Are Stored

Out of the box, ColdFusion stores client variables in the server's Registry and will delete all client variables for any visitors who don't return to your site for 90 or more days. You can, of course, tweak these behaviors to suit your needs. This section discusses the client-variable storage options available.

Adjusting How Long Client Variables Are Kept

Normally, client variables are maintained on what amounts to a permanent basis for users who visit your site at least once every 90 days. If a user actually lets 90 days pass without visiting your site (for shame!), all of their client variables are purged by ColdFusion. This helps keep the client-variable store from becoming ridiculously large.

To adjust this value from the default of 90 days, do the following:

1.

Open the ColdFusion Administrator.

2.

Navigate to the Client Variables page.

3.

Under Storage Name, click the Registry link.

4.

Change the Purge Data for Clients That Remain Unvisited For value to the number of days you want; then click Submit Changes.

NOTE

Remember, there isn't a separate time-out for each client variable. The only time client variables are automatically purged is if the client browser hasn't visited the server at all for 90 days (or whatever the purge-data setting has been set to).


Storing Client Variables in a Database

ColdFusion can store your client variables in a database instead of in the Registry. This will appeal to people who don't like the idea of the Registry being used for storage, or who find that they must make the Registry very large to accommodate the number of client variables they need to maintain. The ability to store client variables in a SQL database is particularly important if you are running several servers in a cluster. You can have all the servers in the cluster keep your application's client variables in the same database, thereby giving you a way to keep variables persistent between pages without worrying about what will happen if the user ends up at a different server in the cluster on their next visit. See the section "Sharing Client Variables Between Servers," later.

NOTE

When using the term Registry, we are referring to the Windows Registry, assuming that ColdFusion Server is installed on a Windows machine. On other platforms, ColdFusion ships with a simple Registry replacement for storage of client variables. Linux and Unix users can still use the default client storage mechanism of the Registry. However, the Registry replacement isn't a high-performance beast, and isn't recommended for applications that get a lot of traffic.


To store your client variables in a database, follow these steps:

1.

Create a new database to hold the client variables. You don't need to create any tables in the database; ColdFusion will do that on its own. If you want, you can use an existing database, but we recommend that you use a fresh, dedicated database for storing client variables.

2.

Use the ColdFusion Administrator to create a new data source for your new database. See Chapter 5, "Introducing SQL," for details.

3.

Navigate to the Client Variables page of the ColdFusion Administrator.

4.

Select your new data source from the drop-down list, then click the Add button. The Add/Edit Client Store page appears, as shown in Figure 20.4.

Figure 20.4. You can have Cold Fusion store your application's client variables in a database, rather than in the Registry.


5.

Adjust the Purge Data for Clients That Remain Unvisited For value as desired. This value was described in "Adjusting How Long Client Variables Are Kept," above. As the page in the Administrator notes, if you are using the client variable database in a cluster situation, this option should be enabled for only one server in the cluster. If you aren't using a cluster, you should keep this option enabled.

6.

Check the Disable Global Client Variable Updates check box unless you are particularly interested in the accuracy of the hitcount and lastvisit properties (see Appendix D, "Special ColdFusion Variables and Result Codes"). In general, we recommend that you check this option, because it can greatly lessen the strain on the database. The only side effect is that client variables will be purged based on the last time a client variable was set or changed, rather than the last time the user visited your site.

7.

Leave the Create Client Database Tables option checked, unless you have already gone through that process for this database in the past.

8.

Click the Submit Changes button.

You now can supply the new data source name to the clientStorage value in the This scope from the Application.cfc file (refer to Table 20.3). All of your application's client variables now will be stored in the database instead of in the Registry.

TIP

If you go back to the Client Variables page of the ColdFusion Administrator and change the Default Storage Mechanism for Client Sessions value to the data source you just created, it will be used for all applications that don't specify a clientStorage attribute (refer to Table 20.3).


Sharing Client Variables Between Servers

As explained at the beginning of this section, ColdFusion tracks each browser by setting its own client-tracking cookie called CFID. Normally, it sets this cookie so that it is sent back only to the server that set it. If you have three ColdFusion servers, each visitor will be given a different CFID number for each server, which in turn means that client variables will be maintained separately for each server.

In many situations, especially if you are operating several servers in a cluster, you will want client variables to be shared between the servers, so that a CLIENT.lastSearch variable set by one server will be visible to the others.

To share client variables between servers, do the following:

1.

Have ColdFusion store your application's client variables in a database, rather than in the Registry. Be sure to do this on all servers in question. For instructions, see the section "Storing Client Variables in a Database," above.

2.

Add a setDomainCookies="Yes" attribute to your application's This scope in the Application.cfc file. This causes ColdFusion to set the CFID cookie in such a way that it will be shared among all servers in the same Internet domain. This is the rough equivalent of using the DOMAIN attribute in a <cfcookie> tag.

Now you can use client variables in your code as you normally would. No matter which server a user visits, ColdFusion will store all client variables in the common database you set up.

NOTE

For cookies to be shared between servers, they all must be members of the same top-level Internet domain (for instance, orangewhip.com).


TIP

For more information about using client variables in a clustered environment, see the "Managing Session State in Clusters" chapter in the companion volume, Advanced Macromedia ColdFusion MX 7 Application Development (ISBN 0-321-29269-3; Macromedia Press).


Backing Up Your Server's Client Variables

If you are keeping client variables in a database, you can back then all up by simply backing up the database itself. If it's an Access or some other file-based database, that entails making a backup copy of the database (.mdb) file itself. Otherwise, you must use whatever backup facility is provided with your database software.

If you are using a Windows server and are keeping client variables in the Registry, you can make a copy of the appropriate portion of the Registry. Just follow these steps:

1.

Open the Registry Editor by selecting Run from the Windows Start menu and then typing regedit in the Run dialog box.

2.

Navigate to the following Registry branch (folder): HKEY_LOCAL_MACHINE\SOFTWARE\Macromedia\ColdFusion\CurrentVersion\Clients

3.

Select Export Registry File from the Registry menu, then save the file wherever you want. Be sure to leave the Selected Branch option enabled.

Storing Client Variables As a Cookie

Somewhat paradoxically, you can tell ColdFusion to store your application's client variables in cookies on the user's machine, rather than on the server side. You do this by setting the clientStorage value in the This scope from the Application.cfc file to Cookie. This basically lets you continue using the CLIENT prefix even if you want the variables to essentially be stored as cookies.

This might be useful, for instance, in situations where you are selling your code as a third-party application and want your licensees to have the option of using a server-side or client-side data store. Unfortunately, the size limitations for cookies will apply (see the section "Cookie Limitations," above). This is a somewhat esoteric subject, so it isn't discussed in full here. Please consult the ColdFusion documentation for more information about this feature.

NOTE

The cookie-storage mechanism for client variables can be useful in a clustered environment or a site that gets an extremely large number of discrete visitors.


NOTE

For more information about using client variables in a clustered environment, see the "Managing Session State in Clusters" chapter in our companion volume, Advanced Macromedia ColdFusion MX 7 Application Development (ISBN 0-321-29269-3; Macromedia Press).


Using Client Variables Without Requiring Cookies

Above, you learned that ColdFusion maintains the association between a browser and its client variables by storing a CFID cookie on the browser machine. That would seem to imply that client variables won't work if a browser doesn't support cookies or has had them disabled. Don't worry; all isn't completely lost.

Actually, ColdFusion normally sets two cookies with which to track client variables: the cfid value already mentioned and a randomly generated cftoken value. Think of cfid and cftoken as being similar to a user name and password, respectively. Only if the cfid and cftoken are both valid will Cold Fusion be capable of successfully looking up the appropriate client variables. If the browser doesn't provide the values, for whatever reason (perhaps because the user has configured the browser not to use cookies or because a firewall between the user and your server is stripping cookies out of each page request), ColdFusion won't be able to look up the browser's client variables. In fact, it will be forced to consider the browser to be a new, first-time visitor, and it will generate a new cfid and cftoken for the browserwhich, of course, means that all client variables that might have been set during previous page visits will be lost.

You can still use client variables without requiring cookies, but it takes a bit more work. Basically, you need to make the cfid and cftoken available to ColdFusion yourself, by passing the values manually in the URL to every single page in your application.

So, if you want your client variables to work for browsers that don't (or won't) support cookies, you must include the cfid and cftoken as URL parameters. So, a link such as

 <a href="MyPage.cfm">Click Here</a> 

would be changed to the following, which would need to be placed between <cfoutput> tags:

 <a href="MyPage.cfm?CFID=#CLIENT.cfid#&CFTOKEN=#CLIENT.cftoken#">Click Here</a> 

ColdFusion provides a shortcut property you can use to make this task less tedious. Instead of providing the cfid and cftoken in the URL, you can just pass the special CLIENT.urlToken property, which always holds the current cfid and cftoken name/value pairs together in one string, including the & and = signs. This means the previous line of code can be shortened to the following, which would still need to be placed between <cfoutput> tags:

 <a href="MyPage.cfm?#CLIENT.urlToken#">Click Here</a> 

TIP

We suggest you always use the urlToken variable as shown here, rather than passing cfid and cftoken separately. This way, you will have fewer changes to make if ColdFusion's method of tracking clients is changed in the future.


You must be sure to pass CLIENT.urlToken in every URL, not just in links. For instance, if you are using a <form> (or <cfform>) tag, you must pass the token value in the form's action, such as this:

 <form action="MyPage.cfm?#CLIENT.urlToken#" method="Post"> 

If you are using frames, you must pass the token value in the src attribute, such as this:

 <frame src="/books/2/448/1/html/2/MyPage.cfm?#CLIENT.urlToken#"> 

And so on. Basically, you must look through your code and ensure that whenever you see one of your .cfm templates in a URL of any type, you correctly pass the token value.

NOTE

Remember that the token value must always be placed between <cfoutput> tags, unless the URL is being passed as an attribute to a CFML tag (any tag that starts with CF, such as <cfform>).


TIP

If users bookmark one of your pages, the cfid and cftoken information should be part of the bookmarked URL, so that their client variables aren't lost even if their browsers don't support cookies. However, if they just type your site's URL into their browsers directly, it's unlikely that they will include the cfid and cftoken. ColdFusion will be forced to consider them as new visitors, which in turn means that the prior visit's client variables will be lost. ColdFusion will eventually purge the lost session (see the section "Adjusting How Long Client Variables Are Kept," above).


NOTE

In addition to the cfid, cftoken, and urlToken properties mentioned here, several other automatically maintained properties of the CLIENT scope are available, including hitCout, lastVisit, and timeCreated.


See Appendix D, "Special ColdFusion Variables and Result Codes."


Storing Complex Data Types in Client Variables

As mentioned earlier, you can store only simple values (strings, numbers, dates, and Boolean values) in the CLIENT scope. If you attempt to store one of ColdFusion's complex data types (structures, arrays, queries, and object references) as a client variable, you get an error message.

You can, however, use the <cfwddx> tag to transform a complex value into an XML-based string. In this serialized form, the value can be stored as a client variable. Later, when you want to use the variable, you can use <cfwddx> again to transform it from the string format back into its complex form.

There isn't space here to discuss the <cfwddx> tag fully, but the following code snippets will be enough to get you started. For more information about <cfwddx>, see Appendix B. For more information about the WDDX technology in general and how it can be used to do much more than this, consult our companion volume, Advanced Macromedia ColdFusion MX 7 Application Development, or visit http://www.openwddx.org.

Assuming, for instance, that myStruct is a structure, the following would store it in the CLIENT scope:

 <cfwddx  action="CFML2WDDX"  input="#myStruct#"  output="CLIENT.myStructAsWddx"> 

Later, to retrieve the value, you could use the following:

 <cfwddx  action="WDDX2CFML"  input="#CLIENT.myStructAsWddx#"  output="myStruct"> 

You then could refer to the values in myStruct normally in your code. If you made any changes to the structure, you would need to store it anew using the first snippet.

NOTE

You can use the isSimpleValue() function to test whether a value can be stored in the CLIENT scope without using this WDDX technique.


NOTE

You can use the isWDDX() function to test whether a client variable actually contains a valid WDDX value.


See Appendix C for details on functions.




Macromedia Coldfusion MX 7 Web Application Construction Kit
Macromedia Coldfusion MX 7 Web Application Construction Kit
ISBN: 321223675
EAN: N/A
Year: 2006
Pages: 282

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net