340 likes | 461 Views
How to create a simple Web application with CGI::Application Template::Toolkit and DBIx::Class. Leonard Miller February 7, 2009. Who is this talk for?. Need to write web applications Don’t want/cannot have a heavy framework Experienced Programmers.
E N D
How to create a simple Web application with CGI::Application Template::Toolkit and DBIx::Class Leonard Miller February 7, 2009
Who is this talk for? • Need to write web applications • Don’t want/cannot have a heavy framework • Experienced Programmers. • Know about CPAN, how to learn from CPAN’s documentation. • Newer programmers that could use a new/better way to organize their code.
Why these three Modules? • Separate out the code to MVC Pieces • Each can be used/tested alone • The modules themselves are easy to use and understand
Why not Catalyst? • mod_perl/fastcgi: You don’t always have the access on the machine to get Catalyst to work. • CGI::Application is a ‘lite’ framework, and as such is much smaller. • Not as big and scary. • Trivial to install in a local ~/lib dir
What is MVC • MVC stands for Model-View-Controller
What is MVC MVC breaks the work into three parts • Model - Short for database model. DBIx::Class does all the database work: inserts/queries. • View - Template::Toolkit does all the view/html work. • Controller - CGI::Application holds all the logic to glue the Model and the View together.
What is MVC • Who has seen code like this: use DBI; my $sql = "select * from users"; my $dbh = DBI->connect( $ds, $un, $pw ); my $sth = $dbh->prepare($sql); $sth->execute(); print "Content-type: text/html\r\n\r\n"; while (my $h = $sth->fetchrow_hashref()) { print ”Name is:".$h->{'first_name'}."<br>\n"; }
What is MVC • Who has seen code like this: use DBI; my $sql = "select * from users"; my $dbh = DBI->connect( $ds, $un, $pw ); my $sth = $dbh->prepare($sql); $sth->execute(); print "Content-type: text/html\r\n\r\n"; while (my $h = $sth->fetchrow_hashref()) { print ”Name is:".$h->{'first_name'}."<br>\n"; }
What is MVC • Who has seen code like this: my $q = new CGI; if ($q-> param('first_name' eq ''){ print input_form(); } else{ my $sql = "insert into users ..."; my $sth = $dbh->prepare($sql); $sth->execute(); print submission_form(); }
What is MVC • Who has seen code like this: my $q = new CGI; if ($q-> param('first_name' eq ''){ print input_form(); } else{ my $sql = "insert into users ..."; my $sth = $dbh->prepare($sql); $sth->execute(); print submission_form(); }
What is MVC • Any questions regarding what MVC is?
CGI::Application A sample program: • Helloworld.cgi <- config info • HelloWorldCgiApp.pm <- controller • Html files: <- View • header.html • body.html • footer.html • DB/Main.pm <- Model • DB/Main/Users.pm • DB/Main/Artists.pm • DB/Main/CDs.pm
CGI::Application helloworld.cgi: use HelloWorldCgiApp; my $helloworld = HelloWorldCgiApp->new(); $helloworld->run();
CGI::Application helloworld.cgi (with config info): use HelloWorldCgiApp; my $helloworld = HelloWorldCgiApp->new ( PARAMS => { tt_config => { INCLUDE_PATH => ".", PRE_PROCESS => 'header.html', POST_PROCESS => 'footer.html', }, hw_string => "Hello world!", }, ); $helloworld->run();
CGI::Application helloworld.cgi (with config info): use lib “~/testdir”; use HelloWorldCgiApp; my $helloworld = HelloWorldCgiApp->new ( PARAMS => { tt_config => { INCLUDE_PATH => ".", PRE_PROCESS => ‘test/header.html', POST_PROCESS => ‘test/footer.html', }, hw_string => "Hello test world!", }, ); $helloworld->run();
CGI::Application HelloWorldCgiApp (continued): package HelloWorldCgiApp; use base 'CGI::Application'; use Template; sub setup { my $self = shift; $self->run_modes( 'mode1' => 'start’, 'mode2' => 'sec_page' ); $self->start_mode('mode1'); }
CGI::Application $q -> param (‘rm’); HelloWorldCgiApp (continued): package HelloWorldCgiApp; use base 'CGI::Application'; use Template; sub setup { my $self = shift; $self->run_modes( 'mode1' => 'start’, 'mode2' => 'sec_page' ); $self->start_mode('mode1'); }
CGI::Application HelloWorldCgiApp (continued): sub start { my $self = shift; my $tt_config = $self->param(‘tt_config’) my $tt = Template->new( $tt_config ); $tt->process('body.html', { hwstr => 'hi world!!!', }, \$html); return $html; }
CGI::Application HelloWorldCgiApp (continued): sub cgiapp_prerun { my ($self, $runmode) = @_; my $q = $self->query; #things you need to run every time #input validation etc. #logging }
DBIx::Class • The mysql table: CREATE TABLE users ( user_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, first_name varchar(75) NOT NULL, last_name varchar(75) NOT NULL, country_code CHAR(2) NULL ); +---------+------------+-----------+--------------+ | user_id | first_name | last_name | country_code | +---------+------------+-----------+--------------+ | 1 | joe | user | US | | 2 | Steve | Jobs | US | | 3 | Bill | Gates | US | | 4 | Larry | Wall | US | +---------+------------+-----------+--------------+
DBIx::Class DB/Main.pm package DB::Main; use base qw/DBIx::Class::Schema/; __PACKAGE__->load_classes(); 1;
DBIx::Class DB/Main/User.pm package DB::Main::User; use base qw/DBIx::Class/; __PACKAGE__-> load_components(qw/PK::Auto Core/); __PACKAGE__->table('users'); __PACKAGE__->add_columns(qw/ user_id first_name last_name country_code /); __PACKAGE__-> set_primary_key('user_id');
DBIx::Class • Using the DBIx::Class Module HelloWorldCgiApp.pm: use DB::Main; my $schema = DB::Main-> connect('dbi:mysql:db','user', 'password'); my @users = $schema->resultset('User')->all; my $users_rs = $schema->resultset('User'); my $user = $users_rs ->next; $tt->process('body.html', { users => [ @users ], user => $user, }, \$html);
DBIx::Class • Using the Module – inserts: my $new_user = $schema-> resultset('User')->new({ last_name => $last_name, first_name => $first_name, }); $new_user->insert;
DBIx::Class Things that you still need to do: • Verify your data -- this is good practice under any circumstances • Open your database connection • Error handling -- did the DB connection open? Did the sql succeed? Unlike some larger frameworks, CGI::Application will not do the error checking for you. • It’s a lite framework, so you still need to do some work
Template::Toolkit • Why use Template::Toolkit? • Common ‘look and feel’ templates. • Easy to change for those people who are better at design than we are. • What type of data is It good for? • arrays • hashes • scalars
Template::Toolkit • Any html file is a TT file! • Simplest usage for a scalar: <html> <body> [% var_name %] </body> </html>
Template::Toolkit • Usage for an Array where users is an array: <body> [% FOREACH item IN users %] [% item %]<br /> [% END %] </body>
Template::Toolkit • Usage where item is a hash: <body> [% item.user_id %] [% item.first_name %] [% item.last_name %] [% item.country %] <br /> </body>
Template::Toolkit • Usage for an Array where users is an array of hashes (like an array of rows from a database): <body> [% FOREACH item IN users %] [% item.user_id %] [% item.first_name %] [% item.last_name %] [% item.country %]<br /> [% END %] </body>
Template::Toolkit • Usage for an Array where users is an array of hashes (like an array of rows from a database): <body> <form> <input type=“hidden” name=“rm” value=“page_2” [% FOREACH item IN users %] ... [% END %] <input type=“submit”> </form> </body>
CGI::Application::Plugin::AbstractCallback CGI::Application::Plugin::ActionDispatch CGI::Application::Plugin::ActionDispatch::Attributes CGI::Application::Plugin::AnyCGI CGI::Application::Plugin::AnyTemplate CGI::Application::Plugin::AnyTemplate::Base CGI::Application::Plugin::AnyTemplate::ComponentHandler CGI::Application::Plugin::AnyTemplate::Driver::HTMLTemplate CGI::Application::Plugin::AnyTemplate::Driver::HTMLTemplateExpr CGI::Application::Plugin::AnyTemplate::Driver::HTMLTemplatePluggable CGI::Application::Plugin::AnyTemplate::Driver::Petal CGI::Application::Plugin::AnyTemplate::Driver::TemplateToolkit CGI::Application::Plugin::Apache CGI::Application::Plugin::Apache2::Request CGI::Application::Plugin::Apache::Request CGI::Application::Plugin::Authentication CGI::Application::Plugin::Authentication::Driver CGI::Application::Plugin::Authentication::Driver::Authen::Simple CGI::Application::Plugin::Authentication::Driver::CDBI CGI::Application::Plugin::Authentication::Driver::DBI CGI::Application::Plugin::Authentication::Driver::DBIC CGI::Application::Plugin::Authentication::Driver::Dummy CGI::Application::Plugin::Authentication::Driver::Filter::crypt CGI::Application::Plugin::Authentication::Driver::Filter::lc CGI::Application::Plugin::Authentication::Driver::Filter::md5 CGI::Application::Plugin::Authentication::Driver::Filter::sha1 CGI::Application::Plugin::Authentication::Driver::Filter::strip CGI::Application::Plugin::Authentication::Driver::Filter::uc CGI::Application::Plugin::Authentication::Driver::Generic CGI::Application::Plugin::Authentication::Driver::HTPasswd CGI::Application::Plugin::Authentication::Store CGI::Application::Plugin::Authentication::Store::Cookie CGI::Application::Plugin::Authentication::Store::Session CGI::Application::Plugin::Authorization CGI::Application::Plugin::Authorization::Driver CGI::Application::Plugin::Authorization::Driver::DBI CGI::Application::Plugin::Authorization::Driver::Dummy CGI::Application::Plugin::Authorization::Driver::Generic CGI::Application::Plugin::Authorization::Driver::HTGroup CGI::Application::Plugin::Authorization::Driver::SimpleGroup CGI::Application::Plugin::AutoRunmode CGI::Application::Plugin::AutoRunmode::FileDelegate CGI::Application::Plugin::BREAD CGI::Application::Plugin::BrowserDetect CGI::Application::Plugin::CAPTCHA CGI::Application::Plugin::CHI CGI::Application::Plugin::Cache::Adaptive CGI::Application::Plugin::CaptureIO CGI::Application::Plugin::CompressGzip CGI::Application::Plugin::Config::Any CGI::Application::Plugin::Config::Context CGI::Application::Plugin::Config::General CGI::Application::Plugin::Config::IniFiles CGI::Application::Plugin::Config::Simple CGI::Application::Plugin::Config::YAML CGI::Application::Plugin::ConfigAuto CGI::Application::Plugin::DBH CGI::Application::Plugin::DBIProfile CGI::Application::Plugin::DBIProfile::Data CGI::Application::Plugin::DBIProfile::Graph::GDGraphInline CGI::Application::Plugin::DBIProfile::Graph::HTML CGI::Application::Plugin::DBIProfile::Graph::HTML::Horizontal CGI::Application::Plugin::DBIProfile::Graph::HTMLBarGraph CGI::Application::Plugin::DBIProfile::Graph::SVGTT CGI::Application::Plugin::DebugMessage CGI::Application::Plugin::DebugScreen CGI::Application::Plugin::DevPopup CGI::Application::Plugin::DevPopup::HTTPHeaders CGI::Application::Plugin::DevPopup::Log CGI::Application::Plugin::DevPopup::Timing CGI::Application::Plugin::Email CGI::Application::Plugin::Eparam CGI::Application::Plugin::ErrorPage CGI::Application::Plugin::Feedback CGI::Application::Plugin::FillInForm CGI::Application::Plugin::Flash CGI::Application::Plugin::FormState CGI::Application::Plugin::FormValidator::Simple CGI::Application::Plugin::Forward CGI::Application::Plugin::HTCompiled CGI::Application::Plugin::HTDot CGI::Application::Plugin::HTMLPrototype CGI::Application::Plugin::HelpMan CGI::Application::Plugin::HtmlTidy CGI::Application::Plugin::I18N CGI::Application::Plugin::JSON CGI::Application::Plugin::LinkIntegrity CGI::Application::Plugin::LogDispatch CGI::Application::Plugin::Mason CGI::Application::Plugin::Menu CGI::Application::Plugin::MessageStack CGI::Application::Plugin::MetadataDB CGI::Application::Plugin::Output::XSV CGI::Application::Plugin::PageBuilder CGI::Application::Plugin::ParsePath CGI::Application::Plugin::Phrasebook CGI::Application::Plugin::ProtectCSRF CGI::Application::Plugin::RateLimit CGI::Application::Plugin::Redirect CGI::Application::Plugin::RequireSSL CGI::Application::Plugin::Routes CGI::Application::Plugin::RunmodeDeclare CGI::Application::Plugin::Session CGI::Application::Plugin::Stash CGI::Application::Plugin::Stream CGI::Application::Plugin::TT CGI::Application::Plugin::TT::LastModified CGI::Application::Plugin::TemplateRunner CGI::Application::Plugin::Thumbnail CGI::Application::Plugin::TmplInnerOuter CGI::Application::Plugin::ValidateRM CGI::Application::Plugin::View::HTML::Template CGI::Application::Plugin::ViewCode CGI::Application::Plugin::YAML There’s more available
Thank you Leonard Miller February 7th Frozen Perl 2009