This document aims to get you up and running with Catalyst.
-NOTE: THIS DOCUMENT IS STILL VERY MUCH AT AN ALPHA STAGE.
-
-Please send comments, corrections and suggestions for improvements to
-A.Ford@ford-mason.co.uk
-
+NOTE: THIS DOCUMENT IS STILL VERY MUCH IN AN EARLY DRAFT STATE. SEE
+THE NOTES AT THE BOTTOM OF THE DOCUMENT.
=head2 Installation
-The first step is to install Catalyst, and the simplest way to do this is to
-install the Catalyst bundle from CPAN:
+The first step is to install Catalyst, and the simplest way to do this
+is to install the Catalyst bundle from CPAN:
$ perl -MCPAN -e 'install Bundle::Catalyst'
-This will retrieve Catalyst and a number of useful extensions and install them
-for you.
+This will retrieve Catalyst and a number of useful extensions and
+install them for you.
=head2 Setting up your application
-Catalyst includes a helper script, C<catalyst.pl>, that will set up a skeleton
-application for you:
-
- $ catalyst.pl My::App
- created "My-App"
- created "My-App/script"
- created "My-App/lib"
- created "My-App/root"
- created "My-App/t"
- created "My-App/t/m"
- created "My-App/t/v"
- created "My-App/t/c"
- created "My-App/lib/My/App"
- created "My-App/lib/My/App/M"
- created "My-App/lib/My/App/V"
- created "My-App/lib/My/App/C"
- created "My-App/lib/My/App.pm"
- created "My-App/Makefile.PL"
- created "My-App/README"
- created "My-App/Changes"
- created "My-App/t/01app.t"
- created "My-App/t/02podcoverage.t"
- created "My-App/script/cgi.pl"
- created "My-App/script/nph-cgi.pl"
- created "My-App/script/fcgi.pl"
- created "My-App/script/server.pl"
- created "My-App/script/test.pl"
- created "My-App/script/create.pl"
-
-This creates the directory structure shown.
-
+Catalyst includes a helper script, C<catalyst.pl>, that will set up a
+skeleton application for you:
+ $ catalyst MyApp
+
+ created "MyApp"
+ created "MyApp/script"
+ created "MyApp/lib"
+ created "MyApp/root"
+ created "MyApp/root/static"
+ created "MyApp/root/static/images"
+ created "MyApp/t"
+ created "MyApp/t/Model"
+ created "MyApp/t/View"
+ created "MyApp/t/Controller"
+ created "MyApp/lib/MyApp"
+ created "MyApp/lib/MyApp/Model"
+ created "MyApp/lib/MyApp/View"
+ created "MyApp/lib/MyApp/Controller"
+ created "MyApp/lib/MyApp.pm"
+ created "MyApp/Build.PL"
+ created "MyApp/Makefile.PL"
+ created "MyApp/README"
+ created "MyApp/Changes"
+ created "MyApp/t/01app.t"
+ created "MyApp/t/02pod.t"
+ created "MyApp/t/03podcoverage.t"
+ created "MyApp/root/static/images/catalyst_logo.png"
+ created "MyApp/root/static/images/btn_120x50_built.png"
+ created "MyApp/root/static/images/btn_120x50_built_shadow.png"
+ created "MyApp/root/static/images/btn_120x50_powered.png"
+ created "MyApp/root/static/images/btn_120x50_powered_shadow.png"
+ created "MyApp/root/static/images/btn_88x31_built.png"
+ created "MyApp/root/static/images/btn_88x31_built_shadow.png"
+ created "MyApp/root/static/images/btn_88x31_powered.png"
+ created "MyApp/root/static/images/btn_88x31_powered_shadow.png"
+ created "MyApp/root/favicon.ico"
+ created "MyApp/script/myapp_cgi.pl"
+ created "MyApp/script/myapp_fastcgi.pl"
+ created "MyApp/script/myapp_server.pl"
+ created "MyApp/script/myapp_test.pl"
+ created "MyApp/script/myapp_create.pl"
+
+This creates the directory structure shown, populated with skeleton
+files.
=head2 Testing out the sample application
You can test out your new application by running the server script that
-catalyst provides:
-
- $ cd My-App
- $ script/server.pl
- [Sun Mar 20 12:31:18 2005] [catalyst] [debug] Debug messages enabled
- [Sun Mar 20 12:31:18 2005] [catalyst] [debug] Loaded engine "Catalyst::Engine::CGI"
- [Sun Mar 20 12:31:18 2005] [catalyst] [debug] Initialized components ""
- [Sun Mar 20 12:31:18 2005] [catalyst] [info] My::App powered by Catalyst 4.26
- [Sun Mar 20 12:31:18 2005] [catalyst] [debug] "My::App" defined "!default" as "CODE(0x83fd570)"
+Catalyst provides:
+
+ $ cd MyApp
+ $ script/myapp_server.pl
+
+ [...] [catalyst] [debug] Debug messages enabled
+ [...] [catalyst] [debug] Loaded plugins:
+ .------------------------------------------------------------------------------.
+ | Catalyst::Plugin::Static::Simple |
+ '------------------------------------------------------------------------------'
+ [...] [catalyst] [debug] Loaded dispatcher "Catalyst::Dispatcher"
+ [...] [catalyst] [debug] Loaded engine "Catalyst::Engine::HTTP"
+ [...] [catalyst] [debug] Found home "/home/users/me/MyApp"
+ [...] [catalyst] [debug] Loaded Private actions:
+ .--------------------------------------+---------------------------------------.
+ | Private | Class |
+ +--------------------------------------+---------------------------------------+
+ | /default | MyApp |
+ '--------------------------------------+---------------------------------------'
+
+ [...] [catalyst] [info] MyApp powered by Catalyst 5.5
You can connect to your server at http://localhost:3000
-The server is now waiting for you to make requests of it. Try using telnet to
-manually make a simple GET request of the server (when telnet responds with
-"Escape character is '^]'.", type "GET / HTTP/1.0" and hit return twice):
+(Note that each line logged by Catalyst begins with a timestamp, which has
+been replaced here with "C<...>" so that the text fits onto the lines.)
+
+The server is now waiting for you to make requests of it. Try using
+telnet to manually make a simple GET request of the server (when
+telnet responds with "Escape character is '^]'.", type "GET / HTTP/1.0"
+and hit return twice):
$ telnet localhost 3000
Trying 127.0.0.1...
Escape character is '^]'.
GET / HTTP/1.0
- HTTP/1.0 200
- Server: Catalyst/4.26
+ HTTP/1.0 200 OK
+ Date: Mon, 07 Nov 2005 14:57:39 GMT
+ Content-Length: 5525
+ Content-Type: text/html; charset=utf-8
Status: 200
- Date: Sun, 20 Mar 2005 12:31:55 GMT
- X-catalyst: 4.26
- Content-length: 40
- Content-Type: text/html; charset=ISO-8859-1
+ X-Catalyst: 5.5
- Congratulations, My::App is on Catalyst!
+ [...]
Connection closed by foreign host.
$
+You can see the full welcome message by visting
+http://localhost:3000/ with your browser.
+
More trace messages will appear in the original terminal window:
- [Sun Mar 20 12:31:55 2005] [catalyst] [debug] ********************************
- [Sun Mar 20 12:31:55 2005] [catalyst] [debug] * Request 1 (0.027/s) [9818]
- [Sun Mar 20 12:31:55 2005] [catalyst] [debug] ********************************
- [Sun Mar 20 12:31:55 2005] [catalyst] [debug] "GET" request for ""
- [Sun Mar 20 12:31:55 2005] [catalyst] [debug] Using default action
- [Sun Mar 20 12:31:55 2005] [catalyst] [info] Processing "!default" took 0.000033s
- [Sun Mar 20 12:31:55 2005] [catalyst] [info] Request took 0.051399s (19.456/s)
+ [...] [catalyst] [debug] **********************************
+ [...] [catalyst] [debug] * Request 1 (0.063/s) [2148]
+ [...] [catalyst] [debug] **********************************
+ [...] [catalyst] [debug] Arguments are ""
+ [...] [catalyst] [debug] "GET" request for "" from localhost
+ [...] [catalyst] [info] Request took 0.046883s (21.330/s)
+ .------------------------------------------------------------------+-----------.
+ | Action | Time |
+ +------------------------------------------------------------------+-----------+
+ | /default | 0.000000s |
+ '------------------------------------------------------------------+-----------'
The server will continue running until you interrupt it.
The application can also be tested from the command line using the generated
-helper script, C<script/test.pl>.
-
+helper script, C<script/myapp_test.pl>.
=head2 Getting your application invoked
-Catalyst applications are intended to be run from mod_perl, but can also be
-run as CGI scripts. Running under mod_perl gives better performance, but for
-development purposes you may want to run your application as a CGI script,
-especially as each changes to your application code take effect under CGI
-without having to restart the web server.
+Catalyst applications are usually run from mod_perl, but can also be
+run as CGI or FastCGI scripts. Running under mod_perl gives better
+performance, but for development purposes you may want to run your
+application as a CGI script, especially as changes to your application
+code take effect under CGI without having to restart the web server.
To run from mod_perl you need to add something like this to your Apache
configuration file:
- <Location /myapp>
+ <Location /MyApp>
SetHandler perl-script
PerlHandler MyApp
</Location>
To run as a CGI script you need a wrapper script like:
#!/usr/bin/perl -w
-
+
use strict;
use lib '/path/to/MyApp/lib';
use MyApp;
-
+
MyApp->run;
-Catalyst outputs a complete HTTP response, which is not what is expected of a
-CGI script. You need to configure the script as a so-called "Non-parsed
-Headers" script for it to function properly. To do this in Apache just name
-the script starting with C<nph->.
+=head2 Examining the generated code
+The generated application code is quite simple and looks something
+like this (comments removed):
+ package MyApp;
+
+ use strict;
+ use warnings;
+
+ use Catalyst qw/-Debug Static::Simple/;
+
+ our $VERSION = '0.01';
+
+ __PACKAGE__->config( name => 'MyApp' );
+ __PACKAGE__->setup;
+
+ sub default : Private {
+ my ( $self, $c ) = @_;
+
+ $c->response->body( $c->welcome_message );
+ }
+
+ 1;
+When the C<Catalyst> module is imported by the application code,
+Catalyst performs the first stage of its initialization. This includes
+loading the appropriate Engine module for the environment in which the
+application is running, loading any plugins and ensuring that the
+calling module (the application module) inherits from C<Catalyst>
+(which makes the Catalyst methods C<config> and C<setup> available to
+the application module).
+
+The call to C<config> sets up configuration data for the application.
+The C<name> parameter is the only required configuration parameter.
+You may also specificy a C<root> parameter, which is the path to the
+directory where documents, images, and templates can be found.
+
+Catalyst associates I<actions> with URLs and on receiving a request
+dispatches to the action that matches to request URL. The call to
+C<setup> in the code above registers a default action. With just
+this action registered the application will respond to all requests
+with the same welcome page.
+
+As you see, the default action is defined as a Private action.
+Most private actions are not directly available from a web url. This
+also includes the built-in actions, 'default', 'begin', 'end', and
+'auto', although they will be called as part of some chains.
+The rest can only be reached by using C<forward>.
+
+The call to the C<setup> method also triggers the second stage of
+Catalyst's initialization process. In this phase Catalyst searches
+for any component modules, locating and registering any actions it
+finds in those modules.
+
+Component modules have names prefixed with the application module name,
+followed by C<Model>, C<View> or C<Controller> (or the optional short
+forms: C<M>, C<V> or C<C>) followed by the component
+name, for example:
+
+ MyApp::Controller::ShoppingCart # long (default) version
+ MyApp::C::ShoppingCart # short version
+
+ MyApp::Model::User # long (default) version
+ MyApp::M::User # short version
=head2 Extending the generated code
-The generated application code looks like this:
+You can start extending the application by adding new actions:
+
+ sub test1 : Global {
+ my ( $self, $c ) = @_;
+ $c->res->body('In a new test action #1');
+ }
+ sub default : Private {
+ my ( $self, $c ) = @_;
+ $c->res->body('Congratulations, MyApp is on Catalyst!');
+ }
+
+ # called like '/article/2005/06'
+ sub archive_month : Regex('^article/(\d{4})/(\d{2})$') {
+ my ( $self, $c ) = @_;
+
+ my $datetime = DateTime->new(
+ year => $c->request->snippets->[0],
+ month => $c->request->snippets->[1]
+ );
+ }
+
+TODO: explain briefly about plugins, actions, and components
+
+If the action is a Regex type, you can use capturing parentheses to
+extract values within the matching URL (2005, 06 in the above
+example). Those values are available in the $c->req->snippets
+anonymous array. See L<Catalyst::Manual::Intro#Actions> for details.
+
+=head2 Hooking in to Template Toolkit
+
+One of the first things you will probably want to add to your
+application is a templating system for generating your output.
+Catalyst works well with Template Toolkit. If you are unfamiliar with
+Template Toolkit then I suggest you look at L<http://tt2.org>, install
+C<Template>, read the documentation and play around with it, and have
+a look at the I<Badger Book> (I<Template Toolkit> by Darren
+Chamberlain, Dave Cross, and Andy Wardley, O'Reilly & Associates, 2004).
+
+You can create a stub Template Toolkit view component by installing
+L<Catalyst::View::TT> and using the create script that Catalyst set
+up as part of the skeleton application:
+
+ $ script/myapp_create.pl view TT TT
+
+ exists "MyApp/lib/MyApp/View"
+ exists "MyApp/t/View"
+ created "MyApp/lib/MyApp/View/TT.pm"
+ created "MyApp/t/View/TT.t"
- package My::App;
+this generates a view component named C<MyApp::View::TT>, which you
+might use by forwarding from your C<end> action:
- use strict;
- use Catalyst qw/-Debug/;
+ # In MyApp or MyApp::Controller::SomeController
- our $VERSION = '0.01';
+ sub end : Private {
+ my($self, $c) = @_;
+ $c->forward('MyApp::V::TT');
+ }
- My::App->config(
- name => 'My::App',
- root => '/home/andrew/My-App/root',
- );
+The generated TT view component simply subclasses the
+C<Catalyst::View::TT> class. It looks like this (with the POD
+stripped out):
- My::App->action(
- '!default' => sub {
- my ( $self, $c ) = @_;
- $c->res->output('Congratulations, My::App is on Catalyst!');
- },
- );
+ package My::App::V::TT;
+
+ use strict;
+ use base 'Catalyst::View::TT';
1;
+C<Catalyst::View::TT> initializes a Template Toolkit object with an
+options hash initialized with built-in default settings followed by
+the contents of the hash C<<%{__PACKAGE__->config()}>>. You can
+configure TT more to your needs by adding a C<new> method to the
+generated TT component:
-You can start extending the application by adding new actions:
+ sub new {
+ my $self = shift;
+ $self->config->{PRE_PROCESS} = 'config/main';
+ $self->config->{WRAPPER} = 'site/wrapper';
+ return $self->SUPER::new(@_);
+ }
+
+=head1 AUTHOR
- My::App->action(
- 'test1' => sub {
- my ( $self, $c ) = @_;
- $c->res->output('In a new test action #1');
- },
- 'test1' => sub {
- my ( $self, $c ) = @_;
- $c->res->output('In a new test action #1');
- },
- '!default' => sub {
- my ( $self, $c ) = @_;
- $c->res->output('Congratulations, My::App is on Catalyst!');
- },
- );
+Andrew Ford, C<A.Ford@ford-mason.co.uk>
+Marcus Ramberg, C<mramberg@cpan.org>
+As noted above, this document is at an alpha stage. My plan for this
+document is as follows:
+=over 4
+=item 1
-=head1 AUTHOR
+Expand this document fairly rapidly to cover topics relevant to
+a newcomer to Catalyst, in an order that can be read sequentially
-Andrew Ford, C<A.Ford@ford-mason.co.uk>
+=item 2
+
+Incorporate feedback
+
+=item 3
+
+Revise the text
+
+=back
+
+Placeholders are indicated by the words: TODO or CHECK
+
+Please send comments, corrections and suggestions for improvements to
+A.Ford@ford-mason.co.uk
=head1 COPYRIGHT
-This program is free software, you can redistribute it and/or modify it under
-the same terms as Perl itself.
+This program is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.