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

I'm trying to use CGI::Application to make a simple web blog. Here's my code:
package Bloggie; use base qw(CGI::Application); use CGI::Carp qw/fatalsToBrowser/; use CGI::Application::Plugin::TT; use DB_File; sub setup { my $self=shift; $self->start_mode('start'); $self->mode_param('rm'); $self->run_modes( 'start' => 'start', 'new post form' => 'new_post_form', 'new post success' => 'new_post_success', 'redirect' => 'redirect', ) } ## overrided so CGI.pm can be replaced by CGI::Simple sub cgiapp_get_query { require CGI::Simple; CGI::Simple->new(); } ## set up preliminary stuff like opening the database. sub cgiapp_init { my $self = shift; my $dataname = "data.dbm"; my %database; dbmopen(%database, $dataname, 0666) or die "Can't open $datana +me: $!\n"; $self->{DATA}=\%database; } ## displays posts sub start { my $self = shift; my $templatename = "start.tt"; my %database = %{$self->{DATA}}; my $posts = $database{POSTS}; my $vars = { "posts" => $posts, }; return $self->tt_process($templatename, $vars); } ## displays form to create new pots sub new_post_form { my $self = shift; my $templatename = "new_post_form.tt"; return $self->tt_process($templatename); } ## displayed on success of a posts ## also writes to database the post that was submitted by new_post_for +m sub new_post_success { my $self = shift; my $templatename = "new_post_success.tt"; my %database = %{$self->{DATA}}; my @posts=(); my $post; #get current posts from database, if they're there #if not, make an empty array. if(defined($database{POSTS})) { @posts = @{$database{POSTS}}; } #get CGI object my $query = $self->query(); #get parameters my $title = $self->param('title'); my $content = $self->param('content'); my $post = { title => $title, content => $content, }; my $vars = { title => $title, content => $content, }; push(@posts, $post); $database{POSTS}=\@posts; return $self->tt_process($templatename, $vars); } 1;
The functions are called in the exact order that they are in. As in, start first, new_post_form next and so on. The thing is, I have my template in new_post_success show me the values of $title and $content and they turn out to be empty! As expected, the central page of the blog never changes (i.e. start() which lists all the current blog entries)! What am I doing wrong? How can I fix it? Also, please reply if you need to see the templates in order to find the solution and I will post them.

Replies are listed 'Best First'.
Re: CGI::Application giving blank forms
by wfsp (Abbot) on Mar 31, 2010 at 07:18 UTC
    See if this helps.
    my $title = $self->param(q{title});
    should be something like
    my $q = $self->query; my $title = $q->param(q{title});
    $self->param(xxx) returns params set by, say, your instance script. You need the params from the query which in CGI::A is in $self->query.

    update: fixed $q->param(q{title});

Re: CGI::Application giving blank forms
by Khen1950fx (Canon) on Mar 31, 2010 at 07:10 UTC
    I fixed a few minor errors in your script. Try this and see if it helps:
    #!/usr/bin/perl package Bloggie; use base qw(CGI::Application); use strict; use warnings; use CGI::Carp qw/fatalsToBrowser/; use CGI::Application::Plugin::TT; use DB_File; sub setup { my $self = shift @_; $self->start_mode('start'); $self->mode_param('rm'); $self->run_modes( 'start' => 'start', 'new post form' => 'new_post_form', 'new post success' => 'new_post_success', 'redirect' => 'redirect', ); } sub cgiapp_get_query { require CGI::Simple; CGI::Simple->new(); } sub cgiapp_init { my $self = shift; my $dataname = "data.dbm"; my %database; die("Can't open ${dataname}: $!\n") unless dbmopen %database, $dataname, 438; $$self{'DATA'} = \%database; } sub start { my $self = shift; my $templatename = 'start.tt'; my %database = %{ $$self->{'DATA'}; }; my $posts = $database{'POSTS'}; my $vars = { 'posts', $posts }; return $self->tt_process( $templatename, $vars ); } sub new_post_form { my $self = shift; my $templatename = 'new_post_form.tt'; return $self->tt_process($templatename); } sub new_post_success { my $self = shift; my $templatename = "new_post_success.tt"; my (%database) = %{ $$self->{'DATA'}; }; my @posts = (); my $post; if ( defined $database{'POSTS'} ) { @posts = @{ $database{'POSTS'}; }; } my $query = $self->query; my $title = $self->param('title'); my $content = $self->param('content'); $post = { title => $title, content => $content }; my $vars = { title => $title, content => $content }; push @posts, $post; $database{'POSTS'} = \@posts; return $self->tt_process( $templatename, $vars ); } 1;
      Error executing run mode 'start': Not a SCALAR reference at Bloggie.pm line 40. at /var/www/Bloggie.pl line 7 ^ that's what CGI::Carp gives me.
        I wonder whether line 40 might be this one, in "sub start...":
        my %database = %{ $$self->{'DATA'}; };
        If so, you should try "$self" instead of "$$self" there. The extra "$" was probably a mistake. (The extra semi-colon, immediately following {'DATA'}, might also be a mistake, which might show up as such when you fix the sigil problem...)
      Can someone please help? It just isn't working!