I have taken to heart a recent comment by Mark Stosberg on the CGIApp mailing list:

"Titanium is just one vision of what can be built on top of CGI::Application. Someone else could easily combine their own combination of CGI::Application and different favorite plugins, and publish that with a different name."

CGI::Application::Structured, like Titanium, is an opinionated framework, based on CGI::Application. Both frameworks includes a number of vetted CGI-App plugins each of which are well documented and tested. C::A::Structured, however takes the view that developer time and consistent projects structures can often be more cost-effective than focusing on the highest performance on low cost hosting solutions. That being said, C::A::Structured can be deployed on CGI, FastCGI or mod_perl based on your needs.

C::A::Structured focuses on:

adequate performance under CGI, but with more focus speed of development.

a well-defined project structure with directories for model classes, controllers and view templates.

integrated form building to simplify creation of complex HTML form elements.

clean url-to-controller mapping by default.

C::A::Structured comes in two packages:

CGI::Application::Strutured - encapsulates the runtime environment.

CGI::Application::Structured::Tools - includes project creation and developemt scripts for developers.

CGI::Application::Structured::Tools are used to generate a micro-architecture and helper scripts that work within that structure to speed development and maintain project structure across development teams and projects. The helper scripts eliminate the tedium of error-prone manual creation of controllers, templates and database mappings and provide a recognizeable structural conventions that reduced stress on the developer when working across multiple apps, or working with other developers code on the same project.

The first script that is used is 'cas-starter.pl'. This script is used to generate the initial project skeleton. The skeleton app contains a base controller class rather than runnable module as would be found in Titanium. Also generated is a default 'Home' controller subclass and a URL dispatcher that is customized to default to the Home controllers generated 'index' runmode.

'create_controller.pl' is used by the developer to generate additional controller subclasses of your base module with a default 'index' runmode and a default TT template for that runmode.

'create_dbic_schema.pl' generates a DBIx::Class::Schema subclass and a set of resultset subclasses for your database. These Object Relational Maps (ORM) will greatly simplify and speed database assess and manipulation in the development process.

Finally CGI::Application::Structured aims to be as compatible as possible with Catalyst. Many plugins used in CGI::Application::Structured are also available for Catalyst, or are even defaults in Catalyst. If your projects needs grow in scope or scale to require Catalyst, porting much of your code will be very easy.

In this tutorial we will build a simplistic database driven web application using CGI::Application::Structured to demonstrate using the starter and helper scripts as well as the minimal required configuration.

CGI::Application::Structured assumes that you have a database that you want to use with the web. If you have a database you can use for this tutorial. Otherwise, jump to the "Create The Example Database" section at the bottom of this page before starting the tutorial.

~/dev$ cas-starter.pl --module=MyApp1 \
--author=gordon \
--email="vanamburg@cpan.org" \
--verbose
Created MyApp1
Created MyApp1/lib
Created MyApp1/lib/MyApp1.pm # YOUR *CONTROLLER BASE CLASS* !
Created MyApp1/t
Created MyApp1/t/pod-coverage.t
Created MyApp1/t/pod.t
Created MyApp1/t/01-load.t
Created MyApp1/t/test-app.t
Created MyApp1/t/perl-critic.t
Created MyApp1/t/boilerplate.t
Created MyApp1/t/00-signature.t
Created MyApp1/t/www
Created MyApp1/t/www/PUT.STATIC.CONTENT.HERE
Created MyApp1/templates/MyApp1/C/Home
Created MyApp1/templates/MyApp1/C/Home/index.tmpl # DEFAULT HOME PAGE TEMPLATE
Created MyApp1/Makefile.PL
Created MyApp1/Changes
Created MyApp1/README
Created MyApp1/MANIFEST.SKIP
Created MyApp1/t/perlcriticrc
Created MyApp1/lib/MyApp1/C # YOUR CONTROLLERS GO HERE
Created MyApp1/lib/MyApp1/C/Home.pm # YOUR *DEFAULT CONTROLLER SUBCLASS*
Created MyApp1/lib/MyApp1/Dispatch.pm # YOUR CUSTOM DISPATCHER
Created MyApp1/config
Created MyApp1/config/config-dev.pl # YOU CONFIG -- MUST BE EDITED BY YOU!
Created MyApp1/script
Created MyApp1/script/create_dbic_schema.pl # IMPORTANT HELPER SCRIPT
Created MyApp1/script/create_controller.pl # ANOTHER IMPORTANT HELPER SCRIPT.
Created MyApp1/server.pl # SERVER USES YOUR CUSTOM DISPATCH.PM
Created MyApp1/MANIFEST
Created starter directories and files

Using the root account is shown here as a worst-practice. You should customize the file supplying the correct database dsn, user and passwords for your database.

If you do not have a database and want to use an example see "Create Example Database" below before continuing.

The configuration file will be found automatically when running with the built in server, but when you deploy your application you may want, or need, to update the config file location in lib/MyApp1/Dispatch.pm to point to your production config file.

From your project root directory run the helper script to generate DBIx::Class::Schema and Resultset packages. This will use the configuration you supplied in config_dev.pl to produce a DB.pm in your apps lib/MAINMODULE directory

CAS comes with CGI::Application::Plugin::DebugScreen. Plugin::DebugScreen provides a very useful stack trace with multi-line source quotations for each level of the stack. cas-starter.pl has put debug.sh in your project root directory. It sets up the environment for Plugin::DebugPage and runs the built in server.

Edit lib/MyApp1/C/Home.pm to generate an error to demonstrate the DebugScreen:

The script will create the 'myapp1_dev' database, create 2 tables and load a few Notice that the create table statements end with 'engine=InnoDB'. This is important since our DBIC generator script will create perl modules to represent database table relationships, based on the metadata in the database. While the InnoDB engine will work, the default engine for mysql will not store the relationship metadata and you would then need to hand-craft the relationships at the botton of the generated DB::Result classes.

If you did not use 'engine=InnoDB' or your database does not support relationships, you can paste the following in the bottom of your "MyApp/DB/Result/Orders.pm" to tell DBIx::Class how the example tables relate: