Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

There is lots of good info in the comments above, but I thought I would try to explain it with an example.

Here is the old fashioned if/elsif/else style:

use CGI qw(:standard); $page = param('page'); # do some header stuff here if ($page eq 'list_products') { # deal with listing products print "......" } elsif ($page eq 'view_product') { # deal with viewing products } elsif ($page eq 'edit_product') { # deal with editing products } elsif ($page eq 'save_product') { # deal with saving product changes } else { # display a default page } # do some footer stuff here

One thing that is difficult to do in that construct is to redirect to a different page. Say a request comes in to save the changes to a product, but there is a validation error, so you want to show the edit_product page again with some error messages. With the if/else construct that is difficult, unless we put all the individual pages into subroutines:

if ($page eq 'list_products') { list_products(); } elsif ($page eq 'view_product') { view_products(); } elsif ($page eq 'edit_product') { edit_product(); } elsif ($page eq 'save_product') { save_product(); } else { start(); } sub list_products { print '...'; }

Now we can call edit_product() from our save_product subroutine to redirect to another page. Now if you ever see something like this in your code, you should really look at using a dispatch table. It removes all the if/elsif stuff, and converts it into a single if statement:

%pages = ( list_products => \&list_products, view_product => \&view_product, edit_product => \&edit_product, save_product => \&save_product, default => \&start, ); if ($pages{$page}) { $pages{$page}->(); } else { $pages{default}->(); } sub list_products { print '...'; }

The dispatch table is much easier to manage, and it doesn't have to test every single possible page in a conditional, since it just does a hash lookup.

Now if you make it this far, then it is just a simple step to migrate to CGI::Application.

use base qw(CGI::Application); sub setup { my $self = shift; $self->run_modes( list_products => 'list_products', view_product => 'view_product', edit_product => 'edit_product', save_product => 'save_product', start => 'start', ); } sub list_products { my $self = shift; return '...'; }

Your functions become methods, and instead of printing to STDOUT, you return the page contents at the end of your runmode method. You still define your dispatch table, but now CGI::Application worries about dispatching to the right method for you. There is even a way to get rid of the dispatch table completely, if you use the CGI::Application::Plugin::AutoRunmode plugin:

use base qw(CGI::Application); use CGI::Application::Plugin::AutoRunmode; sub list_products :RunMode { my $self = shift; return '...'; }

Now we simply use an attribute to mark which methods are valid runmodes.

There are other things that you can benefit from. There are a whole slew of plugins that make a lot of tedious tasks very easy. For example, the ValidateRM plugin which was already mentioned. Also, if you want Sessions, just add use CGI::Application::Plugin::Session to the top of your module, and then anywhere in your runmode methods you can call $self->session which will return you a CGI::Session object. Cookies are automatically sent for you, and sessions are created on demand (ie the first time you call $self->session so there is no wasted effort if sessions are not used on a request).

There are countless other examples (search CPAN for CGI::Application and you will see lots of other plugins.

The reason you can benefit from all this when using CGI::Application is because you are using a common way to organize your application. In other words, you can look at CGI::Applicaton as being an open standard on how to organize and build a web application in perl (there are lots of others as well like Catalyst, Mason, etc...). The important bit is that you are doing things the same was as many others are. That means that you can share ideas and code (ie plugins) with countless other people. If you go your own route, you have to build all that integration yourself, and you are unlikely to be able to easily share anything you build with other, since they probably aren't following your application structure.

It is worth the effort to figure out why people are doing things this way. In the end you will benefit a great deal from the hard work of others that have run into the same things that you will undoubtedly run into.

Updated: fixed a couple spelling and grammar mistakes.

In reply to Re: CGI::Application - why? by cees
in thread CGI::Application - why? by gunzip

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (1)
As of 2022-01-21 05:55 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (57 votes). Check out past polls.