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

Not all that new to Perl, however this is my first post.

I have a web based application that currently uses the method "function = script". In other words each script is a function. ie:

addfoo.cgi;editfoo.cgi;etc....

I recently became interested in the idea of run-modes so that my application would be a little more coherent and also so that I would learn a bit more about perl. I am currently looking at CGI::Application and CGI::Session. While I understand the concepts and can even write a small test app. My knowledge of OO and perl is limiting my fully utilizing these modules.

So I thought I would ask the wisdom of those in-the-know. Now I have checked both the CGI::App mailing list as well as this forum. But most posts only have small sections of sudo-code that, while helpful, have not illuminated my current challenge. So here is the overview of what I am trying to accomplish (this is a generic version of the actual app. I fugure this should be enough to get started in the right direction)

Directory structure:
/public_html/myapp
/public_html/myapp/cgi-bin
/public_html/myapp/htdocs
/public_html/myapp/templates
/public_html/myapp/lib

Main script in ../cgi-bin "myapp.cgi".
Supporting modules are in ../lib.
Templates (template::toolkit based) are in ../templates.

The basic outline of functions (run-modes??) are:

--No login required--
main
search

--login required--
add_foo
edit_foo
delete_foo

The question is two-fold:

1. how to handle login/authentication including handling state
2. a brief overview of how to incorporate many run-modes.

Here is what I thought I would do, let me know where I falter and/or point out possible better practices if you may.

In MyApp.pm I would do something like (truncated where possible):

package MyApp
use base CGI:App
sub setup { my $self = shift; $self->start_mode('main'); $self->mode_param('cmd'); $self->run_modes( 'main' => 'main', 'search => 'search', 'addfoo' => 'addfoo', 'editfoo' => 'editfoo', 'deletefoo' => 'deletefoo' ); sub cgiapp_prerun { # determine run-mode # set/get session # is user logged in? return ok || goto login mode if run mode requires login and user is + not logged in. } sub login { # display login page if no params # not sure how to get back here, but verify user and password # if not valid go to login with error message else.. # set/get session and update logged in to 1. }

I am figuring that the bulk of the run-modes will be held in separate modules that are located under ../lib. But I am not exactly sure how to go out doing that. In other words, do I make them true packages or simple subroutine repositories that I require in at the right moments?

I guess where I am getting stuck is wrapping my head around the concept that I no longer worry about what action is being performed (to a degree) as CGI::App is handling it through run-modes. Instead of me using a crap-load of if/else statements.

Which also leads to to the question How do I handle excessive run-modes. It seems sad to do a run mode for each "screen". I would rather do something like:

myapp.cgi?cmd=foo?action=add

I have seen this before, but where would the corresponding code go? in the foo.pm module? Would that mean then that I am merely MOVING the if/else statements not REMOVING them?

So, if someone could give me a basic example of how to accmplish the above task that would be great. I am not looking for explicit code. But a general overview of the process would be great. I am sure many have been down this path and have much to offer. I feel that I am so close to understanding, but until I can use it in practice, it will be at best obscured by limited knowledge in this area of Perl.

Sorry for the long post :o)

If anyone wants to offer some specifc help, I would be glad to provide my IM name (or via email) and take it off-line.

Edited by castaway, swapped pre tags for code tags.

Replies are listed 'Best First'.
Re: question regarding small CGI based application
by freddo411 (Chaplain) on Oct 15, 2003 at 18:23 UTC
    You are on the right track. Stick to it, accept that it will take a bit of work to get into things, but you will be saving lots of work in the long run.

    First off, don't worry about having lots of run modes. That's normal. You want one for every screen. These run modes will be very thin though, because you will call other subroutines to do all the work.

    Second, in your example code, in prerun, you don't need to determine the runmode (that's done for you).

    You might also write the entire login/check credentials as a seperate related CGI::App. This is good for later code reuse on different projects. You can call this from your other application. In general, you want to have all the runmodes for one generalized webapp bundled together. An example I wrote is a "contact" webapp that has screens for new/edit/delete of "contacts" which are stored in a DB. Very reusable across projects.

    It is a matter of taste, but I keep all the run modes in one file. The subroutines that "do stuff", ( my model of the Model-View-Controller paradigm ) go in another module.

    Lastly, CGI::App used with CGI::Application:ValidateRM (which uses Data::Validate) allows for really user-friendly and programmer friendly HTML form validation and error handling.

    Keep us apprised of your progress. I am pleased to share ideas here on perlmonks.

    cheers

    -------------------------------------
    Nothing is too wonderful to be true
    -- Michael Faraday

Re: question regarding small CGI based application
by valdez (Monsignor) on Oct 15, 2003 at 18:26 UTC

    First of all, welcome to the Monastery!

    Many answers to your questions can be found reading the CGI::Application wiki and the mailing list messages archived here.

    Ciao, Valerio