http://qs1969.pair.com?node_id=100315

Item Description: Framework for building reusable web-applications in an object-orientated and extensible fashion

Review Synopsis:


 
CGI::Application
 

 
Item description : Framework for building reusable web-applications in an object-orientated and extensible fashion
Review Synopsis : An excellent and well-thought out module implementing powerful and downright easy methods to write and build CGI-based applications.
 

 
Why use CGI::Application?
 

 
The CGI::Application module implements this object-orientated framework within which to build your application by creating a super-class within which specific 'run-modes' can be defined. Each run-mode can be correlated to a particular stage of the HTML/CGI user interface. Furthermore, the CGI::Application module implements methods to address the CGI.pm and HTML::Template modules, facilitating powerful methods by which to build extensible and portable web applications - It is obvious that the module author, Jesse Erlbaum (jesse at vm dot com), has put a lot of work into the development and writing of this module.
 
This module allows you to do away with ugly code through the combination of CGI.pm, HTML::Template and methods provided by CGI::Application to implement persistent variables across execution states.
 
(Part of the reason too as to my personal usage of this module is its integration with my preferred templating framework, HTML::Template - Different web application frameworks were reviewed by princepawn at Web Application Frameworks and their Templating Engines with a Comparative Study of Template and HTML::Template)
 

 
Why avoid CGI::Application?
 

 
There seems to be few reasons why to avoid using the CGI::Application module - Usage may not be necessary if persistence and state methods are implemented with other frameworks such as Apache::Session, HTML::Mason or HTML::Embperl.
 

 
How to use CGI::Application?
 

 
The documentation for the CGI::Application module is excellent and covers the building of a (theoretical) database search application. In short, this module promotes the building of applications as self-styled modules based on the CGI::Application framework - The end script (application) consists of an instance script and a module package.
 
An example instance script may look like this:
 

#!/usr/bin/perl # Use our self-styled application module built on the CGI::Applicati +on framework # use self; # Create constructor for our application module (self->new()) and ex +ecute this module in the desired run mode (self->run()) - The desired + run mode is set via the value of a CGI parameter specified by the mo +de_param() method of this module (see self-styled CGI::Application mo +dule package). # my ($application) = self->new(); $application->run(); exit 0;

 
The corresponding module (self) based on the CGI::Application framework may look like this:
 
package self; sub setup { my ($self) = shift; # Set the CGI parameter from which the run-mode of the applicati +on is derived to be 'stage' - This method allows you to set your own +run-mode specifier, passed to your CGI script via hidden HTML form in +put tags # $self->mode_param('stage'); # Set the matched run-mode / subroutine functions to determine w +hich function should be executed for a given run-mode - This method i +s that which allows reusable code to be easily implemented for separa +te run-mode. # # In this example, the subroutines 'display_form' and 'display_r +esults' have been specified to run for run-modes '1' and '2' respecti +vely. The subroutines can be defined as either a hard reference to t +he run-mode method or the name of the run-mode method to be called. # $self->run_modes({ '1' => \&display_form, '2' => 'display_results', }); # Set the mode which should be run in the first instance of the +script, where no run-mode may be specified by a passed CGI variable - + By default, this mode is called 'start', which too must be reference +d to a subroutine via the run_modes() method. # $self->start_mode('1'); }; 1;

 
This is a very basic example of the totality of module framework required to implement the CGI::Application framework - The example above is lacking the referenced subroutines display_form and display_results but provides a clear example of HOW the module framework works.
 
Additional methods within the CGI::Application framework include:
 
param()
 
This method allows to create parameter references which can be referenced across all module/application run modes - This method is most obviously used in the setup() method to implement such references such as DBI connections, HTML::FormValidator schema, etc. eg.
sub setup { my ($self) = shift; $self->mode_param('stage'); $self->run_modes({ '1' => \&display_form, '2' => 'display_results', }); $self->start_mode('1'); # Create DBI connection handle and make accessible to all run-mo +des via CGI::Application param() method # $self->param('dbh' => DBI->connect()); };
teardown()
 
The paired partner of setup(), this method is implemented automatically after the application is run and can be used for clean up persistent variable and database connections. eg.
 
sub teardown { my ($self) = shift; # Disconnect the (persistent, with Apache::DBI) DBI handle creat +ed in setup() and passed via the param() method # $self->param('dbh')->disconnect; };

 
query()
 
This method retrieves the CGI.pm object (CGI->new()) created with the instance of your self-styled CGI::Application module. All methods for CGI.pm can be applied to the blessed reference returned.

 
load_tmpl()
 
This method creates a HTML::Template object (HTML::Template->new()), allowing HTML templates to be employed, aiding in the pyrrhic (depending on your viewpoint) goal of separating code and design. All methods for HTML::Template can be applied to the blessed reference returned.

 
Tips and Gotchas for CGI::Application
 

 
The primary note made about run-mode methods in the CGI::Application documentation is to avoid printing directly to STDOUT, instead returning the HTML output ($html->output, if $html is a HTML::Template blessed reference created via load_tmpl()) at the end of the run-mode subroutine to the CGI::Application framework.
 
For example:
 
# An example run-mode method # sub display_page { my ($self) = shift; # Create a HTML::Template blessed reference with the template fi +le, page.html # my ($html) = $self->load_tmpl('page.html'); print STDOUT $html->output; # printing template output direc +tly to STDOUT (*BAD*) return $html->output; # return template output to CGI: +:Application framework for display (*GOOD*) };

 
With the handling of HTML output to STDOUT by the CGI::Application framework rather than within the run-mode subroutine itself, header types and properties should also not be directly manipulated via CGI methods within run-mode methods. Instead, the CGI::Application framework provides two methods for handling header types and properties indirectly - These methods are described below:
 
header_type(<'header' || 'redirect'>)
 
This method specifies the type of HTTP headers which should be sent back to the client browser by the CGI::Application framework.

 
header_props()
 
This method specifies the HTTP header properties which should be sent back to the client browser by the CGI::Application framework - This method correlates to the header() (and redirect()) methods of the CGI.pm module.

 
Another tip in the documentation of CGI::Application is the definition the run-mode 'AUTOLOAD' - This run-mode is evoked if the mode_param() CGI parameter calls a run-mode definition not matched to a package subroutine via run_modes() method. This allows the the implementation of 'user-friendly' error pages rather than the default CGI::Application behaviour to croak() on such errors. If evoked, the name of the intended run-mode passed via the mode_param() CGI parameter is passed to the AUTOLOAD run-mode as an argument.