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

I'm having problems with Sessions in CGI:Application
I have a short example site setup here, my code is below
When I navigate I see my main site menu repopulated from session, and normal site contents (links) are displayed.
It works ok accessed as index.pl with no parameters, untill I sent a url to someone with parameters, I think I'm not dealing with sessions properly or something like that.
The apache log says "error execurin runmode, attempt to set parameter 'Main_navigation_menu' with a scalar". Its not getting populated automatically.
Index.pl
I took the advice, cut out all the fat to the minimum to show the problem.
index.pl #!/usr/bin/perl use MyTestApp; my $menu = MyTestApp->new(PARAMS => { cfg_file => 'menu.conf' }); $menu->run();
MyTestApp.pm package MyTestApp; use strict; use warnings; use DBI; use HTML::Template; use CGI::Application::Plugin::Session; use CGI::Application::Plugin::ConfigAuto (qw/cfg/); use CGI::Application::Plugin::DBH (qw/dbh_config dbh/); sub setup { my $self = shift; $self->start_mode('Startup'); $self->tmpl_path('Templates/'); $self->run_modes( 'Startup' => 'Startup', 'Page' => 'BuildPage', ); }; sub cgiapp_init { my $self = shift; $ENV{'ORACLE_HOME'} = $self->cfg('Oracle_Home'); $self->dbh_config( $self->cfg('dsn'),$self->cfg('dbuser'),$self->cfg +('dbpass') ); $self->session_config( CGI_SESSION_OPTIONS => [ "driver:File", +$self->query, {Directory => $self->cfg('Session_Path')} ] ); } sub Startup { my $self = shift; my $q = $self->query(); my $template = $self->load_tmpl('index.tmpl'); $template->param( SiteName => $self->cfg('SiteName') ); my $sth = $self->dbh->prepare("SELECT SUB_PAGE_ID, DESCRIPTION, LI +NK_TYPE FROM MYTABLE WHERE CODE=? ORDER BY ITEM") or die "Can't prepair statement: $self->DBI::errstr"; $sth->execute("1") or die "Can't execute Statement: $DBI::errstr"; + # Main menu Menu is always code 1. my ( $Sub_page_ID, $Description, $link_type, @DBRows ); $sth->bind_columns(\($Sub_page_ID, $Description, $link_type, )); while ($sth->fetch) { if(uc($link_type) eq 'SUBM'){ my $url = "index.pl?rm=Page&code=".$Sub_page_ID; push @DBRows, { LINK=>$url, DESCRIPTION=>$Description }; } } $template->param( Main_navigation_menu => \@DBRows ); $self->session->param( MAINMENU => \@DBRows ); return $template->output(); } sub BuildPage { my $self = shift; my $dbh = $self->dbh(); my $q = $self->query(); my $RequestCode = $q->param("code"); my $RequestItem = $q->param("item"); my $template = $self->load_tmpl('index.tmpl'); $template->param( SiteName => $self->cfg('SiteName') ); my $sth; if ( $RequestItem ){ $sth = $self->dbh->prepare("SELECT SUB_PAGE_ID, LINK_TYPE FROM + MYTABLE WHERE CODE=? AND ITEM=? ORDER BY ITEM") or die "Can't prepai +r statement: $self->DBI::errstr"; $sth->execute($RequestCode, $RequestItem) or die "Can't execut +e Statement: $self->DBI::errstr"; }else{ $sth = $self->dbh->prepare("SELECT SUB_PAGE_ID,LINK_TYPE FROM +MYTABLE WHERE CODE=? ORDER BY ITEM") or die "Can't prepair statement: + $self->DBI::errstr"; $sth->execute($RequestCode) or die "Can't execute Statement: $ +self->DBI::errstr"; } my ( $Sub_page_ID,$link_type ); $sth->bind_columns(\($Sub_page_ID, $link_type)); my @DBRows; while ( $sth->fetch ) { if( uc($link_type) eq 'SUBM' ){ my $url; if( defined($Sub_page_ID) ){ $url = "index.pl?rm=Page&code=".$Sub_page_ID; }else{ $url = "javascript:history.go(-1)"; } push @DBRows, { LINK=>$url }; } $template->param( RESULTS => \@DBRows ); } $template->param( Main_navigation_menu => $self->session->param('M +ain_Main_navigation_menu_menu') ); return $template->output(); } sub teardown { my $self = shift; $self->dbh->disconnect(); $self->session->flush if $self->session_loaded; } 1;
Am I not understanding sessions properly? If not can someone help me to fix this by showing an example of how to use sessions to achieve similar?
How Can I recreate variables from session of from new if session does not pre exist?

Replies are listed 'Best First'.
Re: CGI::App + Session value question
by meraxes (Friar) on Jan 22, 2009 at 22:01 UTC

    That error is coming from HTML::Template in this line:

    $template->param( Main_navigation_menu => \@DBRows );

    ... not the session. I suspect a dump of @DBRows would illuminate the problem.

    Update: After a second look at this, if you were to send a link to someone with rm=Page this'll probably may go boom because there's been nothing placed in that session parameter (since the user never went to "Startup" first. Perhaps some logic in the BuildPage runmode that will force them over to the Startup Page if the session var isn't set. CGI::Application::Plugin::Forward is handy for this.

    --
    meraxes
Re: CGI::App + Session value question
by clscott (Friar) on Jan 23, 2009 at 00:20 UTC
    Why isn't TestApp a sub-class of CGI::Application or is that a cut-n-paste error?
    --
    Clayton