blank.gif
webreview.com - Cross-Training for Web Teams
Search for: 
Jump to:
blank.gif
blank.gif

 
 

A Songline PACE Production



Revisiting the Database Application

by Brent Michalski
Oct. 23, 1998
 
 

We completed our database application a couple of weeks ago, but after completing the project, I identified a few changes which would make it even better. I found that although the application could do many things, it couldn't sort. The data can be hard to read if it is not in some type of order. This week we will add code to sort the database, and produce a more complete database application.
 
View the demo


View the demo of this week's program.

Sorting and tweaking

The code we will look at in this article adds the ability to sort records on whatever field the user chooses.

I have also made a few tweaks to the database application, to make it more portable and easier to install. I felt that it was rather annoying to require a complete database.cgi file for each different database that you want. So, I made some modifications and now all you need to do is create a 3 line configuration file and then use that file as an option to the call to the database (database.cgi?config.txt).

I am not going to cover the changes made to accomodate the new configuration file in this article. I put comments in the configuration file that explain what each line does. If you've been following along with our progress on this project, the changes from the previous version should be pretty obvious when you run the application and view the complete program code. We have listed all the previous pieces of this project in the sidebar at right.

Diving in 

I struggled with the sorting routine for quite a while before I got it to work correctly. If I hadn't had such a hard time with it, I would have implemented it in a previous column. Although it doesn't take a lot of code to do our sorting, it is quite complex and very picky.

I want to thank Tom Christiansen and Nathan Torkington for writing the excellent Perl Cookbook. The Perl Cookbook pointed me in the right direction to get the sorting code working. If you haven't seen a copy of it, find it at your local bookstore or library and read it. It is a great book!

Since the program has grown again, I am presenting the code a bit differently this week to save space. I am only going to show and comment on the lines that have changed or been added for our sorting routine. The complete database script code is available in a separate file.

I have numbered the lines of code, the line numbers are not part of the program. The line numbers simply make it easier for me to talk about the program.

...

19: $sort = $q->param(sort_on);

...

40,55 & 87:   &sort_db;

...

313:   print<<HTML;

314:     </FONT></TD></TR><TR>

315:     <TD><FONT FACE="ARIAL" SIZE=2><B>

        Sort On:</B></FONT></TD>

316:     <TD><FONT FACE="ARIAL" SIZE=2>

317: HTML

318:   $x=0;

319:   $CH = "CHECKED";

320:   foreach $field (@fields){

321:     print "<INPUT TYPE=radio NAME=sort_on

        VALUE=$x $CH>\u$field";

322:     $x++;

323:     $CH="";

324:   }

...

363: sub sort_db{

364:   foreach $curr (@results){

365:     ($key,@rest) = split(/\|/, $curr);

366:     $max = @fields;

367:     $code='$record{$key} = { key => "$key", ';

368:     for($x=0;$x<$max;$x++){

369:       $code .= "\$fields[$x] => \"\$rest[$x]\",\n";

370:     } # End of for

371:     $code .= '};';

372:    eval $code;

373:   } # End of foreach

374:   $sort_on = "$fields[$sort]";

375:   @results=();

376:   foreach $rp (sort { $a->{$sort_on} cmp

        $b->{$sort_on} } values %record){

377:     $new_rec = $rp->{key};

378:     for($x=0;$x<$max;$x++){

379:       $new_rec .= "\|$rp->{$fields[$x]}";

380:     } # End of for

381:     push @results, $new_rec;

382:   } # End of foreach

383: } # End of sub sort_db

Line-by-line explanation 

Line 19: We added this line to get the field the user wants to sort on from the calling web page. It is passed from the new radio button added to the form in lines 313-317. 

Lines 40,55 & 87: These lines all call the sort_db subroutine. The first 2 call it from within our modify subroutines and the last one calls it from our search subroutine. 

Lines 313-317: These lines are a here document that prints out the code to add the extra row to our user input page. 

Line 318: Initializes our $x variable to 0. 

Line 319: Initializes our $CH variable to the value CHECKED. We do this so that when the web page is displayed, the first item in the radio button group is automatically selected. 

Line 320: Begins a foreach loop that goes through each of the items in @fields and stores them in the variable $field

Line 321: Prints the HTML for the radio button group, one radio button at a time. Each time through the loop, a new radio button is created. 

Line 322: Increments our $x variable. We use the $x variable as the value of the radio button. This value is then passed to the program in line 19. 

Line 323: Sets our $CH variable to nothing. Since we only wanted the first item in our radio button group to be selected, we set this value to nothing and for the remaining passes through the loop, the radio buttons are not selected. 

Line 324: Ends our foreach loop. 

Line 363: Begins our sort_db subroutine. 

Line 364: Begins a foreach loop that goes through each of the items in @results and stores the value in $curr. Remember, the array @results is created by our search_database subroutine, it contains all of the matching records. 

Line 365: Splits the current record into a variable called $key and an array called @rest. We now have the record key stored safely in a variable and the fields of data stored in an array. 

Line 366: Creates a variable called $max and sets its value to the number of elements in our @fields array. The @fields array is created in our new configuration file

Line 367: Begins the creation of a block of code which becomes our record. This record is very similar to a struct in C. 

Line 368: Begins a for loop> that goes through each of our fields and creates another line in our code block. 

Line 369: Appends data onto the end of our $code variable. 

Line 370: Ends our for loop. 

Line 371: Finishes off our $code variable. We now have a variable called $code that looks something like this: 

$record{$key} = { 

key        => "$key",

$fields[0] => "$rest[0]",

$fields[1] => "$rest[1]",

$fields[2] => "$rest[2]",

$fields[3] => "$rest[3]",

$fields[4] => "$rest[4]",

};

Line 372: evals the code in the variable $code. eval takes the code passed to it, and executes it as if it were a tiny Perl program. We create the code this way and then eval it in order to take an array of almost any length, @fields, and make it into a record. 

Line 373: Ends our foreach loop. 

Line 374: Creates a variable called $sort_on. It gets the value of $fields[$sort] which is interpolated and turned into the field name of what will be sorted on. For example, if $field[2] contains Last Name, and $sort equals 2, then once we execute this line of code, the value stored in $sort_on would be Last Name

Line 375: Empties our @results array. This is the same array that was filled by our search_database subroutine. We have to empty it, otherwise we will get duplicates of every item when we push values onto it below. 

Line 376: Begins a foreach loop that goes through each of the values in %record and sorts them on the field we passed in the variable $sort_on. A record pointer, $rp, is created each time through the foreach loop. We then access the data via the record pointer. 

Line 377: Creates a new variable called $new_rec. This variable becomes the new record once we are done with it. We take each of the fields and reconstruct the record into the format that our database expects it. Remember that we split the record above, here we are un-splitting it and initially setting it to the key value of the current record. 

Line 378: Begins a for loop that creates our new record. 

Line 379: Appends the next field onto the end of our $new_rec variable. Notice that we put a pipe symbol |, before each value. We do this because we chose to use the pipe symbol as our field delimiter in the database. 

Line 380: Ends our for loop. 

Line 381: pushes the new record onto the @results array. This reconstructs the @results array and places the items in the array in the order we wanted them sorted. 

Line 382: Closes the foreach loop. 

Line 383: Closes the sort_db subroutine. 

Wrapping it up 

We've once again finished our database application, now with sort features! This program will work on either UNIX or NT. Just remember that if you are on NT, you need to put complete paths with drive letters in the configuration file. 

When programming, be persistent! I knew exactly what I wanted this sorting subroutine to do, but it didn't work the way I thought it should. Persistence pays off. If I had given up, the database application wouldn't be complete. Even programmers with a lot of experience can struggle to get code working, but by struggling you learn much more than you can if someone simply tells you how to do it and not why it works. 

No pain, no gain :-) 

See you next week! 


Source Code for Revisiting the Database Application
View and download the source code for this week's article.
Next: Scoring a Web Page with Perl and LWP
Prev: A Complete Database Application in Perl

Web Review copyright © 1995-99 Songline Studios, Inc.
Web Techniques and Web Design and Development copyright © 1995-99 Miller Freeman, Inc.
ALL RIGHTS RESERVED