matthx has asked for the wisdom of the Perl Monks concerning the following question:

#!/usr/bin/perl print "content-type:text/html\n\n"; require "formparser.lib"; &parseform; use DB_File; my $guestbook = "/home/matt/gbook"; my $name = $formdata{'name'}; my $email = $formdata{'email'}; my $comments = $formdata{'comments'}; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdist) = localtime( +time); my $postime = "$hour:$min $mday-$mon-$year"; dbmopen %BOOK, $guestbook, 0666 or die "Cant open $guestbook: $!\n"; %BOOK = ('name' => $name, 'email' => $email, 'comments' => $comments, 'postime' => $postime ); @array1 = values(%BOOK); print "@array1"; print "size of hash: " . keys( %BOOK ) . ".\n"; dbmclose(%BOOK);
Hi guys, im having a problem with the code above, im trying to create a simple guestbook application. The script recieves values from a html form and I want these to be saved to a dbm database. The problem is every time I send data the values dont seem to stay in the database.

Replies are listed 'Best First'.
Re: perl dbm problem
by xdg (Monsignor) on Aug 31, 2005 at 11:36 UTC

    Right now, your code overwrites the entire %BOOK hash each time. If you weren't using DB_File and your html library, and wanted to store several entries in %BOOK and then print them out, how would you do it? That doesn't change under DB_File, since it just stores the hash on disk.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: perl dbm problem
by gargle (Chaplain) on Aug 31, 2005 at 11:38 UTC

    Hi,

    You seem to be overwriting the entries in your dbm, no? Only the last values entered in the form are saved. Won't you better first read your dbm from disk in your hash and then add the new entries from the form? That way you'll preserver your old entries.

    Also, keys( %BOOK ) won't give you a number but will show you 'name','email','comments', and 'posttime', not a number. Is that what you want? (I goofed up!)

    -- if ( 1 ) { $postman->ring() for (1..2); }

      Also, keys( %BOOK ) won't give you a number but will show you 'name','email','comments', and 'posttime', not a number.

      That is not correct. keys in a scalar context returns the number of keys:

      my %hash = ( foo => 1, bar => 2, baz => 3 ); print "There are " . keys( %hash ) . " keys\n"; # output There are 3 keys
Re: perl dbm problem
by graff (Chancellor) on Aug 31, 2005 at 22:02 UTC
    If you want a single database (dbm) record to contain "name, email, comments, postime", and you want the dbm file to contain more than one record, you'll probably want to use "email" as the hash/dbm key, and then combine the other three strings into a single scalar string -- something like this:
    $BOOK{$email} = join "\t", $name, $comments, $postime;
    Presumably, two different people will not enter different names, comments, etc, using the same email address -- if they do, the one who comes in later will overwrite the one who came in earlier.

    This way, when you get the keys from the dbm file, it will be the list of email addresses for people who have signed in; for each key, you can then fetch the name, comments, etc.