Day 2 - Handel

Handel 1.0 and Catalyst: Closer than ever

Introduction

Just over a year ago, Handel made its way out unto the world as a basic framework for cart/order/checkout operations complete with basic Catalyst integration using helpers. Since that time, Handel has undergone a lengthy rewrite to make it easier to customize and integration into Catalyst has never been easier.

Getting Started

Before we get started, you will need to install the following requirements:

Catalyst 5.7+
Handel 1.0 (or 0.99_15+)

It would also be a good time to check out the original Handel article on Perl.com:

http://www.perl.com/pub/a/2005/11/17/handel.html

Create a new Catalyst application

Every catalyst example starts with this:

    $ catalyst.pl MyApp
    [ output snipped ]

Add the Handel bits

Now that we have a new application, we need to have Handel create cart/order/checkout bits for us. The Handel helper will create a full set of subclasses for doing Cart/Order/Checkout operations inside and outside of Catalyst, as well as all of the templates, models and controllers needed to use them.

To create 'the full shebang', call the Handel helper and pass in the dsn/user/password where the database will be located:

    $ cd MyApp
    $ script/myapp_create.pl Handel dbi:SQLite:data/handel.db
    [ a lot of output creating models a view, controllers and test stubs snipped ]

Installing the database schema

Now that we have a basic cart/order/checkout application, we need a place to store our data. If you would like to make any schema changes, now is a great time to do it. The installed schema is based on the storage classes created above.

For example, if you want to change the name of the table the carts are stored in, or add a column, simply change the appropriate options in MyApp::Storage::Cart:

    __PACKAGE__->table_name('mycarttable');
    __PACKAGE__->add_column('mynewfield' => {
        data_type   => 'VARCHAR',
        size        => 25,
        is_nullable => 1
    });

To install the schema into an existing database, or create a new database (SQLite), simply run the provided handel script, passing it the same information you supplied above:

    $ script/myapp_createdb.pl --default

    Installed/created database schema

If you are installing the schema into a database other than SQLite, make sure the database exists and the user/password supplied has permission to create tables and indexes.

Houston, we need sessions!

The one thing the helper doesn't do for you is load session support needed for Handel to function. To do that, add the session store/state modules of your choosing to MyApp.pm:

    use Catalyst qw/
        -Debug
        ConfigLoader
        Session
        Session::State::Cookie
        Session::Store::File
        Static::Simple
    /;

Fire it up

Now the moment of truth! Start your new app:

    $ script/myapp_server.pl
    [ application startup output snipped ]
    You can connect to your server at http://localhost:3000

In your browser, navigate to the static products page:

    http://localhost:3000/static/products.htm

Pick the product of your choosing and hit [Add To Cart]. You should now have yourself a nice shiny new shopping cart page. Try saving and restoring your cart..checking out...viewing previous orders. Enjoy!

Where to go from here

Now that you have a nice new shiny cart/order/checkout application the real fun begins. The new version of Handel allows you to store carts and orders in separate databases or in completely different stores like XML, Text, LDAP, or even things like Google Checkout (once someone writes the glue. :-])

Because all of the necessary subclasses have been created, the only changes required to do such magic comes down to changing the MyApp::Storage::* classes:

    MyApp::Storage::Cart;
    __PACKAGE__->storage_class('Handel::Storage::LDAP');
    __PACKAGE__->set_ldap_options(...);
    1;

That's it. The cart class MyApp::Cart works the same. And speaking of subclasses, keep in mind that you can use your classes outside of Catalyst too, like in a command line application:

    #!/usr/bin/perl -w
    use strict;
    use warnings;
    use MyApp::Cart;

    $ENV{'HandelDBIDSN'} = '/home/me/MyApp/data/handel.db';

    my $cart = MyApp::Carts->search({id => $ARG[0])->first;
    print "Total: ", $cart->subtotal;
    ...

Happy carting!

NOTE: The default cart code makes no attempt to verify the price of the part submitted. Please take the time to change MyApp::Controller::Cart to get the pricing information from your products/inventory database.

SEE ALSO

AUTHOR

Christopher H. Laco <claco@chrislaco.com>