簡易CGI Webフレームワーク

友達に、ちょっとしたサイトを作る話を貰ったとき(仕事じゃなく)、perlでやることにしました。CGIとHTML::Templateは、使うけど黒魔術じゃないというframeworkはできないものかと思いながら、作ってみました。

結果頼まれたサイトはなかなか完成せず、なんちゃってframework作りに興味が向いている自分に気が付いてしまいました。そのときの、簡単な使い方と中枢部のソースです。名前はMizincoとしています。機能も少ないから身のたけに合った名前ではないでしょうかね。

  • 簡単な使い方
    • CGIファイル
#!c:/perl/bin/perl
use strict;
use warnings;
use Mizinco;
my $controller = new Mizinco();
$controller->proc();
exit;
#=====================================================================
# Action
#=====================================================================
  package Action;
use CGI::Carp qw(fatalsToBrowser);
  sub default {
return {redirect_to => "hello"};
}
  sub hello {
my ($q, $session, $infos) = @_;
my $response_data = {message => "hello, dynamic world. <" . localtime . ">"};
return {
forward_to => "hello.html",
response_data => $response_data
};
}
    • テンプレートファイル
<html>
<body>
<h1>hello, world.</h1>
<p><tmpl_var name='message' escape='html'></p>
</body>
</html>
  • frameworkの中枢部のソース
package Mizinco;
use 5.008002;
use strict;
use warnings;
our $VERSION = '0.01';
use Carp;
use CGI;
use CGI::Session;
use HTML::Template;
use HTML::FillInForm;
use Mizinco::Utils;
sub new {
my ($class, %args) = @_;
my $q = new CGI or die "failed to create CGI instance: $! $@\n";
my $session = new CGI::Session("driver:File", $q, {Directory => './session'})
or die "failed to create CGI::Session instance: $! $@\n";
my $self = {
query => $q,
session => $session,
args => \%args,
entry_cgi => $q->url(-absolute, 1),
app_name => Mizinco::Utils::get_app_name($q)
};
return bless $self, $class;
}
sub proc {
my $self = shift;
my $q = $self->{query};
my $session = $self->{session};
#get command from PATH_INFO.
my (undef, $command, @info) = split('/', $ENV{'PATH_INFO'});
$command ||= "default";  #default action name.
#execute action.
my $action_results = do {
no strict "refs";
&{"Action::${command}"}($q, $session, \@info);
};
#validate error.
if ($action_results->{validate_errors}) {
$action_results = Mizinco::Utils::restore_action_results($action_results, $q, $session) ;
}
#redirect, if you appointed it. and return.
if ($action_results->{redirect_to}) {
print $q->redirect("$self->{entry_cgi}/$action_results->{redirect_to}");
return;
}
#prepare view.
my $template = new HTML::Template(filename => "html/" . $action_results->{forward_to},
associate => $q,
die_on_bad_params => 0,
loop_context_vars => 1) or die "failed to create HTML::Template instance: $! $@\n";
my $response_data = $action_results->{response_data};
map {$template->param($_ => $response_data->{$_});} (keys %$response_data);
$session->param("_action_results", $action_results);
print $session->header(-type => 'text/html', -charset => 'Windows-31J');
my $output_buf = $template->output;
#replace mizinco tags.
$output_buf =~ s/\<mizinco_action_url\>/$self->{entry_cgi}/ig;
$output_buf =~ s/\<mizinco_app_url\>/$self->{app_name}/ig;
#fill in form and output html document.
print new HTML::FillInForm()->fill(scalarref => \$output_buf, fobject => $q);
}
sub DESTROY {
my $self = shift;
$self->{session}->save_param($self->{query});
}
1;

まぁ、これだけでは動かないんですが。(あと2,3ファイル必要)

いつの日か、まとめて出せる状態になればいいなとは思ってるけど。。。

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.