Using What We've Learned

This month Mr. Lerner shows us how to set up a web site using many of the techniques he's taught us over the past months.
Putting It All Together

The trick now is to create a template that does the following:

  • Grabs the value of person_id from any cookie that the user's browser might send.

  • Uses the value of person_id to retrieve information about the user from the database.

  • Uses the information from the database to create a personalized HTML page greeting the user.

Getting the value of the user's cookie is almost as simple as setting it. Just as our CGI program can set one or more cookies when it returns an HTTP header to the user's browser, the value of the cookie is sent to our server in the HTTP headers accompanying any request we might receive. Once our person_id cookie is set on the user's computer, every visit to our site will be prefaced with the name and value of person_id. We can retrieve the values of all cookies on our system with a call to the “cookie” method, just as we used it to create our cookie.

Listing 6 contains a very short CGI program ( that prints the names and values of all cookies sent to a particular server. Remember that cookies are only sent to the server that originally set them—so while your browser might contain a large number of cookie name-value pairs, the output from will only display those created by your server.

In, we iterate through each of the cookies sent to the web server. But for our particular purposes, we are only interested in a single cookie, “person_id”. We can retrieve that by using the “cookie” method in the following way:

my $person_id = $query->cookie("person_id");

Assuming that a cookie named “person_id” was sent to the web server (meaning that the “person_id” cookie had been set by a program on that server in the past), its value would now be available in the variable $person_id. We can then use $person_id as a unique key in our “birthdays” table, allowing us to retrieve information about returning users.

Among other things, we must ensure that the template handles the possibility that a user with a cookie might not appear in the database, or that a user might go to the customized home page without a cookie. In the test template (cookie.tmpl), this is handled in a fairly crude way, printing out both the value of the user's “person_id” cookie and the number of rows matching this value of person_id in the database. In the example template shown in Listing 7, we include the following code:

if (($person_id == 0) || ($sth->numrows == 0))
    $outputstring .=
        "<P>Error retrieving information.</P>\n";
    $outputstring .= "<P>person_id (cookie) = \"
    my $numrows = $sth->numrows;
    $outputstring .=
      "<P>Rows returned from table = \"
    $outputstring .=
        "<P><a href=\"/birthday.html\">";
    $outputstring .=
        "Enter your birthday</a></P>\n";

This code checks to see if $person_id (which is sent as a cookie from the user's browser and should correspond to a single row in the “birthdays” table) is equal to 0, which can also mean that it is not set. If $person_id is 0, then we have no cookie on record for this user. This does not necessarily mean that the user has never visited our site before—some users reject cookies because of privacy concerns, others use multiple browsers (each of which keeps its own list of cookies) and still others might be accessing the web from multiple computers. But our system does ensure that users accessing our site from the same computer (and the same browser) will see their birthday displayed whenever they come to our system.

We also compare $sth->numrows with 0 to see if no rows were returned from the database. It is quite possible that a user might have visited our site long ago, and that the cookie from that visit remained on that user's computer—but that all early visitors' entries in the database were somehow deleted. Under such circumstances, $sth->numrows will return 0 (meaning that no rows had a person_id column matching $person_id from the user's cookie), and we have to request a new birthday entry from the user.

If the query did return a row (and we know that it will return one row at the most, since person_id must be unique), then we have to grab that row with $sth->fetchrow, and then read the values of the resulting array into our variables. In this particular case, we do nothing more than print them out:

        while (my @arr = $sth->fetchrow)
          my ($firstname, $lastname, $email,
                $birthdate) = @arr;
        $outputstring .=
                "<P>firstname =
        $outputstring .=
                "<P>lastname =
        $outputstring .=
                "<P>email = \"$email\"</P>\n";
        $outputstring .=
                "<P>birthdate =

Of course, if we were interested in doing something a little more interesting, we could do so by taking the values returned by $sth->fetchrow and using the resulting variables in the title of the HTML page or a comparison of today with the user's birth date. The point is that the database is a means for storing information between invocations of the CGI program. Once the information has been read into the CGI program from the database, we can use that information just as easily as if we had assigned the variables at the beginning of its invocation.