[Search Criteria Storage and Restoration]

Greg Willits, July 29, 2003

There are two cornerstone elements to saving a user's search criteria and restoring when regenerating the initial found records list: first we must save the actual search criteria, and second when loading the list page we need a method to declare whether we want a prior search restored or a new search started.

Before digging into the code, let's first look at the flow of operations involved. Assume we have a site visitor at a search form on the page search.lasso. We'll assume the form is a simple one with just fields which will be interpreted as contains in our search inline (no advanced search options like begins with, equals, or others). The user enters some text into one or more fields, and clicks submit.

On the response page (list.lasso) we will have one or more action_param name-value pairs which have defined our search, and we'll use those in some form to populate the search inline. The search will generate a list of records and a link for each record to a detailed page.

The user now clicks a link to see a single record in detail, and is forwarded to the detail.lasso page. When done with this page, the user wants to return to the original list with all search criteria in tact. At this point, one could argue the browser back button accomplishes that, and in most cases it probably does. So, let's look at a scenario where the detail record requires a number of pages to review. An example, a Human Resources database of employees. Such a database would have basic employee contact info, timecard history, health ins info, 401k info, position and pay history, etc. We may need to bounce around several pages in order to view the details. At some point the user wants to return to the original list.

Storing the Search Criteria

How do we restore a previously generated found records list? First we have to store the actual search criteria. The place to do that is on the list.lasso page. Regardless of whether there is only one search form, or perhaps even several locations where a search may be either explicitly defined by a visitor or implicitly defined in your code, there will be some parameters submitted to the list.lasso page. That's the place we want to capture and store them.

There's a few ways to go about capturing the search criteria. There's some easy ways that are a little open to security leaks, and some more secure methods which require a little more setup effort. I am only going to discuss the latter.

Where are we going to store this criteria? In either a cookie, or a database session record, and possibly both.

What format are we going to use to store the search criteria? I prefer a concatenated string with text delimiters. Whether the criteria is stored in a database or cookie, the value has to be text. If we use arrays, then we have to serialize them which just makes the data larger. The internal routines to build the search can quickly convert those strings to arrays using ->split.

The format I use is:

name=value\r
... n repeats ...
name=value\r

Where name is the input field name, and value is, of course, the value enter by the user. To keep this data set as small as possible, I only store pairs where a value was submitted which is easy to do based on the way that the form will only pass these inputs anyway. If for some reason you have to keep track of empty values, that can be added.

For security purposes, you want to explicitly define which input fields are to be included in the criteria list. So, something like this:

var:'fw_srchStore'=(string);

if: action_param:'fldA';
      $fw_srchStore += ('fldA=' + action_param:'fldA' + '\r');
/if;
if: action_param:'fldB';
      $fw_srchStore += ('fldB=' + action_param:'fldB' + '\r');
/if;
... etc ...

To automate this a little, we can take this approach:

var:'fw_srchStore'=(string);

var:'fw_srchInputs'=(array:'fldA','fldB',...);
iterate: $fw_srchInputs, var:'thisInput';
      if: action_param:$fw_thisInput;
              $fw_srchStore += ($fw_thisInput + '=' + (action_param:$fw_thisInput) + '\r');
      /if;
/iterate;

If you want to store empty values as well, then eliminate the IF statements.

If you also have popups to declare search method such as contains, beginswith, etc, then we can extend our data structure in some manner such as:

name:::method=value\r
... n repeats ...
name:::method=value\r

Use ::: or ``` or --- or any such delimiter, and alter the routine above which builds the concatenated string to accommodate this.

Now, we have a single data structure which contains all of our search criteria. There's a few options at this point for storing it. One is that a uniquely named cookie or variable can be defined which is specific to this search only. Create a cookie name and store the $fw_srchStore variable as its contents, or replace the $fw_srchStore variable name with something unique to just this search and store it to a Lasso or homegrown database session record.

In either case, if this is a sensitive database with sensitive field data and therefore possibly sensitive search strings being entered, blowfish the $fw_srchStore variable before storing it.

Controlling New and Restored Searches

We have outlined that when the list.lasso page is loaded, it should save the search form criteria. Well, that's fine if we have just come from the search form. What if we have come from another page and expect the search criteria to be restored? How do we get that data back?

Actually the first question is, how does list.lasso even know in the first place whether it is to be starting a new search and storing criteria, or restoring criteria?

We could try to use [referrer_url] and test the page name. If it is our search form, we know to start a new search. The problem is that this information is not always available, and some applications may have mini search forms all over the site which point to this list page.

I find the most reliable way to handle this is that any form which points to this list page must have a hidden input. I called it "fw_srch" and it contains a value to indicate the search mode. I use the literal strings "new" and "restore" so the source code is easy to interpret (compared to 1/0, Y/N, true/false). The only value that matters is "restore." I set a hidden input like so:

<input type="hidden" name="fw_srch" value="restore">


If fw_srch is anything but "restore," then the decision routine on list.lasso assumes a new search. I typically use an explicit "new" hidden input as well on the search forms just for clarity in behavior of the form.

So, the routine at the top of list.lasso now looks more like:

var:'fw_srchStore'=(string);

var:'fw_srchInputs'=(array:'fldA','fldB',...);
if: action_param:'fw_srch' == 'restore';
      ..... retrieve criteria .....
else;
      iterate: $fw_srchInputs, var:'thisInput';
              if: action_param:$fw_thisInput;
                      $fw_srchStore += ($fw_thisInput + '=' + (action_param:$fw_thisInput) + '\r');
              /if;
      /iterate;
      // use cookie or session
      cookie_set: 'your_cookie_name' = $fw_srchStore, -path='/';
/if;


Just to be clear, this hidden input does not get propagated from page to page. Only at the point in which any link goes to the list page and expects a restored search list, does this input need defined.

Retrieving the Search Criteria

It should be apparent by this point that if the fw_srch hidden input is "restore" that the routine at the top of list.lasso will fetch the cookie or session variable to retrieve the data. I put this data in var:'fw_srchRestore' in order to be clear about its purpose. Once retrieved the data can be disassembled back into the name-value pairs originally submitted.

Here we hit a snag. How do we recreate action_param pairs? Well, we don't. It's possible through tricky overriding of internal variables and other methods, but there's a simpler and more practical method. All of the action_param pairs from the search form should first be converted to variables. If you already have a routine to convert action_param pairs to vars, then you're already there. If not, do it here. So, once again, a slight change to our routine:

var:'fw_srchStore'=(string);

var:'fw_srchRestore'=(string);
var:'fw_srchInputs'=(array:'fldA','fldB',...);
if: action_param:'fw_srch' == 'restore';
      ..... retrieve criteria .....
else;
      iterate: $fw_srchInputs, var:'thisInput';
              if: action_param:$fw_thisInput;
                      var:$fw_thisInput = action_param:$fw_thisInput;
                      $fw_srchStore += ($fw_thisInput + '=' + (var:$fw_thisInput) + '\r');
              /if;
      /iterate;
      // use cookie or session
      cookie_set: 'your_cookie_name' = $fw_srchStore, -path='/';
/if;

And now after we include the restoration routine (for which I'll assume a cookie and the use of name=value pairs without methods) we get:

var:'fw_srchStore'=(string);

var:'fw_srchRestore'=(string);
var:'fw_srchInputs'=(array:'fldA','fldB',...);
if: action_param:'fw_srch' == 'restore';
      $fw_srchRestore = cookie: 'your_cookie_name';
      if: $fw_srchRestore;
              $fw_srchRestore = ($fw_srchRestore->split:'\r');
              iterate: $fw_srchRestore, var:'fw_srchTerm';
                      var:(($fw_srchTerm->split:'=')->get:1)=(($fw_srchTerm->split:'=')->get:2);
              /iterate;
      /if;
else;
      iterate: $fw_srchInputs, var:'thisInput';
              if: action_param:$fw_thisInput;
                      var:$fw_thisInput = action_param:$fw_thisInput;
                      $fw_srchStore += ($fw_thisInput + '=' + (var:$fw_thisInput) + '\r');
              /if;
      /iterate;
      // use cookie or session
      cookie_set: 'your_cookie_name' = $fw_srchStore, -path='/';
/if;

[inline: ...do the search routine here...]

This routine now knows whether or not the page should store new search criteria and execute a new search based on a form, or restore old search criteria previously stored.

Executing the Search

I won't go into much detail here, except to explain that after the above routine, regardless of whether the search is new or restored, you now have a list of variable name-value pairs to build your search inline with. The search inline itself doesn't need to have any knowledge of whether the search is new or restored as we equalized the input with the above routine at the top of the page prior to the search.

Email:


Password:



Articles