Sign In/My Account | View Cart  
advertisement


Listen Print Discuss

Rapid Website Development with CGI::Application
by Mark Stosberg | Pages: 1, 2, 3, 4

New Dispatcher Provides Clean URLS

A large project built with CGI::Application typically has many small "instance scripts" that drive modules full of run modes. All of these instance scripts look basically the same:

use Project::Widget::View;
my $app = Project::Widget::View->new();
$app->run();

A corresponding URL might look like:

/cgi-bin/project/widget/view.cgi?widget_id=23

CGI::Application::Dispatch 2.0 allows you to replace all of these instance scripts with a single dispatch script to produce much cleaner URLs. Such a dispatch script might look like:

#!/usr/bin/perl
use CGI::Application::Dispatch;
CGI::Application::Dispatch->dispatch(
        prefix              => '',
        table               => [
            ':app/:rm/:id'  => {},
        ],

);

Now add a dash of mod_rewrite magic provided in the documentation, and the URL will transform from:

/cgi-bin/project/widget/view.cgi/detailed_view?widget_id=23

to:

/widget/detailed_view/23

Clean and simple.

The widget_id is easily accessible from within the run mode:

my $widget_id = $self->param('id');

The dispatcher takes care of that detail for you, saving some manual munging of PATH_INFO.

First-Class Templating Support

While CGI::Application integrates by default with HTML::Template, it seems an equal number of the users prefer the Template Toolkit templating system. Both camps now have access to several new templating-related features.

Default template names

To keep the code cleaner and consistent, it's now possible to generate template names automatically. Typically, you want to load one template to correspond with each run mode. Simply loading a template might look like:

    sub my_run_mode: Runmode {
        my $self = shift;

        # XXX The old way, with redundant file name 
        # my $t = $self->load_tmpl('my_run_mode.html');

        # Look Ma! No explicit file name needed!
        my $t = $self->load_tmpl;
        return $t->output;
    }

Easy access to the application object from the template

The TT plugin introduced easy access to the CGI::Application object from the template, allowing easy constructions by using the c parameter to access the application object.

Hello [% c.session.param('username') || 'Anonymous User' %]
<a href="[% c.query.self_url %]">Reload this page</a>

Authors of open source web applications will surely appreciate the AnyTemplate plugin, which allows you to use a single templating syntax in your code, and lets users choose the templating system that best integrates with their existing project. There was no ready-made way to do this in the past.

Conveniently, HTML::Template and TT users can use a familiar syntax to drive AnyTemplate.

TT style:

$self->template->process('file_name', \%params);

HTML::Template style:

# Yes, it really can be identical to the standard load_tmpl() syntax!
my $template = $self->load_tmpl('file_name');
$template->param('foo' => 'bar');
$template->output;

A great example of this template abstraction is CGI::Application::Search, a reusable application that integrates with the Swish-E search engine. Whether you prefer HTML::Template or Template Toolkit, it's easy to add this as a search solution for a larger project--even if the rest of your website does not use CGI::Application.

CGI::Application also offers improved support for other output formats. The Stream plugin makes it a snap to stream a document to the user, such as a PDF or Excel file that is built on the fly. This saves the busy work of remembering the related details for unbuffered output, binmode, file chunking, and MIME types. That now takes basically one line of syntax:

$self->stream_file( $file );

The XSV plugin simplifies building CSV files. This tedium is now a single function call for simple cases:

  return $self->xsv_report_web({
    fields     => \@headers,
    # Get values from the database
    values     => $sth->fetchall_arrayref( {} );
    csv_opts   => { sep_char => "\t" },
    filename   => 'members.csv',
  });

Pages: 1, 2, 3, 4

Next Pagearrow