Innovative Web Solutions
Blue Star have a proven reputation for building
high performance web designs and web applications
backed up by strategic online marketing campaigns.

Diarmuid Ryan & Associates

Posts Tagged ‘Perl’

executing program in perl with qx//

Wednesday, December 5th, 2007

Stumbled across a nice perl tid-bit in my daily blog and forum participation, the backtick operator has always been a thorn in debugging many Perl scripts in the past, its so easy to miss the damn things…

I discovered a much more elegant solution today, the qx// operator. Which makes for a much more readable and less error prone syntax…

Post to Twitter Post to Facebook Post to MySpace

Building an application framework in mod_perl using CPAN modules - Part 1

Friday, November 10th, 2006

Author: Diarmuid Ryan

Introduction

There are many application frameworks around for various programming languages to simplify the development of web applications, sometimes though there comes a time when the ready-made solutions don’t cover what you need to do or don’t do what you need in an intuitive way. An application framework is often referred to as middle-ware or back-end system. The goal is to take the heavy work away from the front-end that serves up to pages, abstract it, and push it down the stack of the operating environment. Common things included to make live easier in developing a web site front-end are handling of database interaction, templating for content and output files, communicating with remote servers, configuration of web site, and handling email. In this article I aim to outline how you can create this functionality through an object-orientated mod_perl approach.

The front-end should make use of separate objects for each page/functional unit of the web site and should inherit from the base class, for our purposes we will call this Base.pm.

Base class, Configuration & Control flow

A global configuration for your website can be used to store common attributes to the web environment, this would include paths and URL locations of content, data, images, etc. You could also include paths to email program or SMTP host used for sending email. Locations of template files you will use for content should also be specified in a configuration file. Other attributes such as domain name, database details such as name, user and password, location of apache http auth password files and general purpose apache configuration directives. A good way to go about creating a system configuration is by defining what you need in a Perl module and call it Constants.pm and include it in the base class you are using to build framework. An example might look something like:

#!/usr/bin/perl

package Website::Constants;

use constant DOMAIN  => ‘www.mydomain.com’;
use constant CONTENT  => ‘/home/httpd/mydomain/content’;
use constant TEMPLATE_PATH => ‘/home/httpd/mydomain/templates’
…

Control flow can be managed by a starter script which accepts what module to use along with its regular CGI parameters. This file should include any global options and/or variables, in our case here we initial a random number with srand to seed random functions and declare our database handle as $dbh.

Note the use of the hash to store object/page modules, using a lookup in this method prevents a nefarious user from inserting malicious code to be executed. The starter script is essential in any mod_perl application for issues regarding scope of persistent variable. For more info see http://perl.apache.org/docs/1.0/guide/porting.html#The_First_Mystery.

Starter script example:

#!/usr/bin/perl

use CGI;
use CGI::Carp qw(fatalsToBrowser);

use lib '/srv/www/www.internationaljobsolutions.com/perl';

use Website::Base;

srand;

use vars qw($dbh);

my $q = new CGI;

my $actions = {
   'Login'    => 'Login',
   'Search'   => 'Search',
   'ProductList'  => ‘ProductList’,
   'ProductDetail' => 'ProductDetail',
   ‘InternalError’ => ‘InternalError’,
   ….
};

my $action = 'Website::Actions::' . ($actions->{$q->param('action')} ||
                                     'InternalError');

eval "use $action";

if ( $@ ) {

   #…eval failed, do error handling here
}

# execute object and return page
$action->new();

Base.pm should contain the bulk of the required methods, any extensions to this should be created as subclasses. Here is an example object constructor for Base.pm which connects us to a database and logs an error if it fails. Every major action such as database interactions, reading parameters, template handling should produce debug error logs.

sub new {

   my $self = [];

   bless($self);

   my $db_name = Website::Constants::DB_NAME;
   my $db_user = Website::Constants::DB_USER;
   my $db_pass = Website::Constants::DB_PASS;

   $dbh = DBI->connect('DBI:mysql:'. $db_name, $db_user, $db_pass);

   $self->[DB_ERROR] = '';

   unless ( defined($dbh) && $dbh ) {
      $self->debug( 1, 'Unable to connect to MASTER DB!' );
      $self->[DB_ERROR] = 'Unable to connect to DB!';
   }

   return $self;
}

In the front end object the constructor would be something similar to this:

sub new {

   my $proto = shift;
   my $class = ref($proto) || $proto;
   my $self = [];

   bless($self, $class);

   $self->SUPER::new(); # inherit Base.pm and any other super-classes

   $self->[PARAMS] = $self->get_cgi_params();
   $self->[COOKIE] = $self->get_cookie(‘cookie_id');
   $self->[TEMPLATE] = Website::Constants::TEMPLATE_PATH;
   $self->[CONFIG] = $self->get_config();

   my $cookie = $self->execute();

   my $file = $self->[TEMPLATE];
   my $params = $self->[PARAMS];

   my $redirect = undef;

   $self->response( $file, $params, $cookie, $redirect  );

   return $self;
}

The object instance defines collections from functions in the Base.pm module such as get_cgi_params(), get_cookie() and get_config().

The execute function handles the specific response to the query, of which there may be one (e.g. a search page and results page). The template attribute would be completed with the method called from the available actions available to execute().

The reponse() could can return a cookie along with content of any type (implemented Base.pm) such as HTML, plain text or an image. The two options available here are to include response() in Base.pm along with its handlers for each output type or create a Response.pm subclass, depending on your requirements. In this tutorial we will cover an HTML output method, fill_template() in Base.pm.

Also it is worth noting that the apache mod_rewrite function could, perhaps should, be used to translate simple paths into parameter lists for both clarity to the user and search engine spiders. An example of a simple rewrite expression in apache configuration:

RewriteEngine On
RewriteRule  ^/ProductItem/id/([0-9]+)$   /perl/go?do=ProductItem&id=$1

Regular expressions are used to rewrite the URL, but that is outside the scope of this article, man perlretut will give you the man pages on Perl regular expressions which use the same syntax.
Templating

Templating can be taken care off quite easily with modules from CPAN, you can take your pick from Template Toolkit or HTML::Template (and probably several others). For this article we will be using HTML::Template. The idea here is to encapsulate the functionality of HTML::Template, extend it if necessary, and create an API interface that will suit our front-end application. Templating is quite an important part of an application framework as it is what ties your data to your visual output. HTML::Template accepts a filename of a template file to create its object. Normally when you want to fill your template you set parameters one-by-one.

The following function could be used to create template and populate with values when all data has been processed for page and should be added to the Base.pm class or subclass.

sub fill_template {

   my $self = shift;
   my $file = shift;
   my $template_params = shift;

   my $template = HTML::Template->new( filename    => $file,
                                       global_vars => 1,
                                       die_on_bad_params => 0 );

   unless($template) {
       $self->debug(1, ‘FAILED TEMPLATE: Could not create document: ’. $file );
   }

   for (keys(%{$template_params})) {
      if ($template->query(name => $_)) {
         $template->param($_ => $template_params->{$_});
      }
   }

   return $template->output();
}

If inherited in the front-end object, this could be accessed as follows in a function in this script:

my $file = Website::Constants::TEMPLATE_PATH . ‘/mytemplate.html’;
my $params = $self->[PARAMS];

$self->fill_template($file, $params);

Coming in Part 2

I will go through database handling, email and remote services using SOAP and XML.

Post to Twitter Post to Facebook Post to MySpace

Perl - The double edged sword

Saturday, August 26th, 2006

Perl is a mighty powerful weapon at the disposal of a web developer, a post-modern language that bridges the gap between modernism and post-modernism, i.e. the double edged sword that is…it is os flexible and comprehensive that it can be an extension of your limbs, or misused sever those limbs…we use perl for the majority of our projects here at Blue Star, mostly adhering to the concept coined by Larry Wall (creator or of perl) that programmers rule by the principles of laziness, impatience and hubris. The self righteous attidute that that the code is elegant and well consctructed regardless of the fact that there are probably dozens of ways to solve a particular problem, and by laziness develops libraries that can be re-used and is proud of the resulting code knowing that it can be used again…it is a post modern paradigm this is clear, yet also leads to duplicity…the many ways of doing one thing, but this is the crux, a problem in perl can be solved in many ways, just be sure that it is re-usuable for to satisfy the impatience and laziness of future projects…yet open enough to be rightously expanded in the future to benefit any other project from the grond up…

Larry Wall on post-modernism

Post to Twitter Post to Facebook Post to MySpace


LinkedIn ProfileBecome Fan on FacebookFollow us on Twitter
Blue Star Web Design Ireland
e: sales@bluestar.ie
t: +353 86 3318412
Tipperary Town

Copyright ©2010 Blue Star