newbie: multi-screen CGI script

D

Don Stefani

Don Stefani humbly exposes his stupidity to the world...

Hello,

Looking at the Perl Cookbook: (Recipe 19:12 Writing a Multiscreen CGI Script)

I'm trying to do this:
<code>
%States = (
'Default' => \&front_page,
'Shirt' => \&shirt,
'Sweater' => \&sweater,
'Checkout' => \&checkout,
'Card' => \&credit_card,
'Order' => \&order,
'Cancel' => \&front_page,
);

if ($States{$page}) {
$States{$page}->(); # call the correct subroutine
} else {
no_such_page();
}
</code>

But I can get the following to work. just fine, but 'The Cookbook' calls my method,
"tedious and clumsy". I'm trying to work away from that! ;-)
I'm testing with just two views, but I'll probably end with six or so.
I must admit I only kind of know what I'm doing. I'm sure that's the key to the problem.
I have a feeling I might be making things too complicated. A good hint and a flaming kick
in the pants are very welcomed. TIA - Don

<code>

#!/usr/bin/perl -w
use strict;
use CGI;
use Lib::AccountMgrGeneral;
use Lib::MysqlModule;
use Lib::WebForms;
my $q = new CGI;
my $amg = new AccountMgrGeneral;
my $mysql = new MysqlModule;
my $wf = new WebForms;

my $view = $q->param('view') || 'srch';

# HTML top-------------------------
print "Content-type:text/html\n\n";
print $amg->header();

if ($view eq 'nsi')
{
print $wf->NameServerInput();
}
else
{
print $wf->SearchForm();
}

# HTML Bottom------------
print $amg->footer();

</code>
 
U

Uri Guttman

DS" == Don Stefani said:
I'm trying to do this:

it is called a dispatch table.
<code>
%States = (
'Default' => \&front_page,
'Shirt' => \&shirt,
'Sweater' => \&sweater,
'Checkout' => \&checkout,
'Card' => \&credit_card,
'Order' => \&order,
'Cancel' => \&front_page,
);
if ($States{$page}) {
$States{$page}->(); # call the correct subroutine
} else {
no_such_page();
}


i prefer to save a hash lookup like this:

if (my $page_sub = $States{$page}) {
$page_sub->(); # call the correct subroutine
}
else {
no_such_page();
}

and don't cuddle elses! (read perlstyle :).
But I can get the following to work. just fine, but 'The Cookbook'
calls my method, "tedious and clumsy". I'm trying to work away from
that! ;-)

#!/usr/bin/perl -w
use strict;
use CGI;

good start
use Lib::AccountMgrGeneral;
use Lib::MysqlModule;
use Lib::WebForms;
my $q = new CGI;
my $amg = new AccountMgrGeneral;
my $mysql = new MysqlModule;
my $wf = new WebForms;

my $obj = Class->new() ;

direct object calls are safer. i think the issue is covered in perlobj.

my $view = $q->param('view') || 'srch';
# HTML top-------------------------
print "Content-type:text/html\n\n";
print $amg->header();
if ($view eq 'nsi')
{
print $wf->NameServerInput();
}
else
{
print $wf->SearchForm();
}

you showed us the dispatch table and here is the working if/else
code. but you haven't stated what happens with your broken code. also
you haven't posted the entire broken script. if you just dropped the
dispatch code into this, it should work but we can't see why it doesn't
from this. note: make sure the dispatch hash is lexical (my) and is
declared and assigned before it is used and outside any sub that uses
it. it is static so doing it inside a sub would be slower (maybe not in
the simple cgi case, but i have seen code where it was in a sub that is
called repeatedly and that is not good).

so put in your dispatch table (2 entries is fine) and tell us what
happens when you run it. also the dispatch table didn't have the same
vars as your code so they have to match. $page needs to become
$view. the cookbook is not written to have its code used literally, you
have to edit names and such to fit your needs.

uri
 
D

Don Stefani

Uri Guttman wrote:
the cookbook is not written to have its code used literally, you
have to edit names and such to fit your needs.

New, yes, but not that new! :)

my $obj = Class->new() ;
direct object calls are safer. i think the issue is covered in perlobj.
Thanks, I'll be looking into that directly.

OK, here's the code with the dispatch table followed by the errors.

<code>
#!/usr/bin/perl -w
use strict;
use CGI;
use Lib::AccountMgrGeneral;
use Lib::MysqlModule;
use Lib::WebForms;
my $q = new CGI;
my $amg = new AccountMgrGeneral;
my $mysql = new MysqlModule;
my $wf = new WebForms;
my $view = $q->param('view') || 'srch';

# HTML top-------------------------
print "Content-type:text/html\n\n";
print $amg->header();

### the subroutines in the table are in WebForms.pm
my %states = {
'srch' => \&SearchForm,
'nsi' => \&NameServerInput
};

if (my $page_sub = $states{$view})
{
$page_sub->(); # call the correct subroutine
}
else
{
print "no such page\n";
}

# HTML Bottom------------
print $amg->footer();
</code>

<errors>
command line:

(NOTE: HTML output good until the good stuff is supposed to happen, then
die.)
perl test2.cgi
Reference found where even-sized list expected at test2.cgi line 18, <>
line 1.
no such page

Browser:
At default page ($views = 'srch')
I get my "no such page" msg.

when I send a param, $views = 'nsi', I get a 500 error.
</errors>

Thanks for your help, I just got a request for this small app and I'm in
the first stages of switching from PHP to Perl. I'm trying to resist the
urge to just do it in PHP. I'm hoping to learn from this project,
although I feel a bit presumptuous. I hope I'm not "asking you to do my
homework" if you know what I mean. My gut tells me the problem is that
the way the table or the $page_sub test is written, it's looking for the
subroutine in the main script. (?)

Thanks,

Don
 
U

Uri Guttman

DS" == Don Stefani said:
Uri Guttman wrote:
the cookbook is not written to have its code used literally, you
New, yes, but not that new! :)

well, we have to make sure! :)
### the subroutines in the table are in WebForms.pm
my %states = {
'srch' => \&SearchForm,
'nsi' => \&NameServerInput
};
Reference found where even-sized list expected at test2.cgi line 18,
<> line 1.

look carefully at the code in the cookbook and your hash
assignment. there is a distinct (but subtle difference). i will let you
do this first before i (or someone else) gives you the answer. it is a
good excercise to compare code with a microscope (char by char). and you
will learn a valuable lesson about hashes and how to initialize them.
no such page
Browser:
At default page ($views = 'srch')
I get my "no such page" msg.
when I send a param, $views = 'nsi', I get a 500 error.
</errors>

fix the first problem and maybe these will go away. many times early
problems cause phony later ones that will magically go away when you fix
the former.
Thanks for your help, I just got a request for this small app and I'm
in the first stages of switching from PHP to Perl. I'm trying to
resist the urge to just do it in PHP. I'm hoping to learn from this
project, although I feel a bit presumptuous. I hope I'm not "asking
you to do my homework" if you know what I mean. My gut tells me the
problem is that the way the table or the $page_sub test is written,
it's looking for the subroutine in the main script. (?)

it is in your dispatch table for sure.

and i gave you homework and didn't do yours! :)

uri
 
D

Don Stefani

Uri said:
look carefully at the code in the cookbook
() not {} duh! That actully crossed my mind (quickly I guess)

But here's the new error on the command line: (dieing at the sub in
question.
<error>
Undefined subroutine &main::SearchForm called at test2.cgi line 25, <>
line 1.
</error>

I made a comment in the code, that the subs are in WebForms.pm,
I need to get at them either in the table or the test?

Thanks,
Don

<code>
#!/usr/bin/perl -w
use strict;
use CGI;
use Lib::AccountMgrGeneral;
use Lib::MysqlModule;
use Lib::WebForms;
my $q = new CGI;
my $amg = new AccountMgrGeneral;
my $mysql = new MysqlModule;
my $wf = new WebForms;
my $view = $q->param('view') || 'srch';

# HTML top-------------------------
print "Content-type:text/html\n\n";
print $amg->header();

# the subroutines in the table are in WebForms.pm
my %states = (
'srch' => \&SearchForm,
'nsi' => \&NameServerInput
);

if (my $page_sub = $states{$view})
{
$page_sub->(); # call the correct subroutine
}
else
{
print "no such page\n";
}

# HTML Bottom------------
print $amg->footer();
 
U

Uri Guttman

DS" == Don Stefani said:
() not {} duh! That actully crossed my mind (quickly I guess)

good, you found it. did you learn the lesson? :)
But here's the new error on the command line: (dieing at the sub in
question.
<error>
Undefined subroutine &main::SearchForm called at test2.cgi line 25, <>
line 1.
</error>
I made a comment in the code, that the subs are in WebForms.pm,
I need to get at them either in the table or the test?

you need to export them into main:: or fully qualify them in the
dispatch table. i assume the module has its own package so those subs
won't be seen by the code refs in the dispatch table as they are not in
main::

the simplest solution is to fully qualify them.
# the subroutines in the table are in WebForms.pm
my %states = (
'srch' => \&SearchForm,
'nsi' => \&NameServerInput
);

'nsi' => \&WebForms::NameServerInput

uri

PS. have you gotten my emails? you sent me one and i haven't heard back
since i replied.
 
D

Don Stefani

Uri said:
PS. have you gotten my emails? you sent me one and i haven't heard back
since i replied.

Emails sent.

That got rid of the command line error, but I get nothing as output in
the browser. Not even my default subroutine. I'm ready to be "tedious
and clumsy" for now in the name of progress! Break-time for bonzo.
I'll get back at this later.

Thanks,

Don
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top