[cgiapp] Some general questions on CGI::App and OO web application
design philosophy
Richard Jones
ra.jones at dpw.clara.co.uk
Sun Jun 7 05:23:24 EDT 2009
Brad Van Sickle wrote:
[ .. ]
> Currently, I'm working on creating a content management system for a
> static website. The CMS has quite a few sections (manage users, manage
> events, manage articles, etc... ) but each section does basically the
> same things (displays the current records, allows you to delete or edit
> current records, allows you to create a new record) Right now I have it
> set up so each section is it's own application. I have an instance
> script and a package for each section. Within that package I change out
> the SQL statements and related code, load different templates for the
> create/edit forms, etc... It works well, but I'm not sure that this is
> the "right" way of doing things.
>
> It seems to me that there is probably a way to do this by using a
> different instance script for each section, but having them all leverage
> the same package by initializing it with section specific data on the
> forms and SQL statements, and than adding in subclasses or instance
> script code for any additional methods that may be required... but I'm
> still kind of new with OO PERL and I can't quite wrap my head around the
> details.
Another way to approach this is to use CGI::Application::Dispatch, and
revert to a single instance script pointing to your Dispatch class, and
let *it* load the relevant controller class. That way you can have an
integrated application with many separate components, for example -
using the MVC approach - UserManager, EventManager, ArticleManager
controller classes. So something like the following would do it:
# myapp.cgi:
use MyApp::Dispatch;
MyApp::Dispatch->dispatch();
# MyApp::Dispatch:
use base 'CGI::Application::Dispatch';
my @config_files = map { '/path/to/app/root/config/' . $_ }
$d->read; # where $d = IO::Dir->new('/path/to/app/root/config')
sub dispatch_args {
return {
prefix => 'MyApp',
table => [
'/' => { app => 'YourDefaultController', rm => 'default_rm' },
# specific matches (optional):
'admin/:app' => { prefix => 'MyApp::C::Admin' },
'admin/:app/:rm' => { prefix => 'MyApp::C::Admin' },
'admin/:app/:rm/:id'=> { prefix => 'MyApp::C::Admin' },
# generic matches:
':app' => { }, # MyApp::C::* - uses default runmode
':app/:rm' => { }, # MyApp::C::* - uses specified runmode
':app/:rm/:id' => { }, # captures 'id' in $self->param('id')
],
args_to_new => {
PARAMS => {
config_files => \@config_files,
},
}
}
# MyApp:Controller::UserManager
use base 'MyApp::Base';
sub default_runmode { ..}
sub display_users { .. }
sub delete_user { .. }
etc
# MyApp::Base # you could put common methods in here eg create
# record, delete record, etc
use base 'CGI::Application';
use CGI::Application::Plugin::TT;
use CGI::Application::Plugin::Session;
etc
Note, I've used 'C' instead of Controller in the dispatch_args() table
definition to save it line-wrapping. See:
http://search.cpan.org/~markstos/CGI-Application-Dispatch-2.16/lib/CGI/Application/Dispatch.pm
for more details.
CAD also works well in mod_perl & fastcgi environments, and also when
using CGI::Application::Server for development.
> Coding that class to handle dynamically passed SQL statements
> and process dynamic forms seems very very difficult to me.
This is where ORM's such as DBIx::Class and Rose come in very useful as
your 'Model' in the MVC architecture, but that's a subject for another time.
--
Richard Jones
More information about the cgiapp
mailing list