features of how Catalyst works and shows how to get a simple application
up and running quickly. For an introduction (without code) to Catalyst
itself, and why you should be using it, see L<Catalyst::Manual::About>.
+For a systematic step-by-step introduction to writing an application
+with Catalyst, see L<Catalyst::Manual::Tutorial>.
=head2 What is Catalyst?
Catalyst is an elegant web application framework, extremely flexible yet
extremely simple. It's similar to Ruby on Rails, Spring (Java), and
-L<Maypole>, upon which it was originally based.
+L<Maypole>, upon which it was originally based. Its most important
+design philosphy is to provide easy access to all the tools you need to
+develop web applications, with few restrictions on how you need to use
+these tools. Under Catalyst, it is always possible to do things in a
+different way. However, this does mean that it is always possible to do
+things in a different way. Other web frameworks are simpler to use and
+easy to get up and running, but achieve this by locking the programmer
+into a single set of tools. Catalyst's emphasis on flexibility means
+that you have to think more to use it. We view this as a feature.
=head3 MVC
the others. Catalyst promotes the re-use of existing Perl modules that
already handle common web application concerns well.
-Here's how the M, V, and C map to those concerns, with examples of
-well-known Perl modules you may want to use for each.
+Here's how the Model, View, and Controller map to those concerns, with
+examples of well-known Perl modules you may want to use for each.
=over 4
=item * B<Model>
Access and modify content (data). L<DBIx::Class>, L<Class::DBI>,
-L<Plucene>, L<Net::LDAP>...
+L<Xapian>, L<Net::LDAP>...
=item * B<View>
=head3 Flexibility
-Catalyst is much more flexible than many other frameworks. We'll talk
-more about this later, but rest assured you can use your favorite Perl
-modules with Catalyst.
+Catalyst is much more flexible than many other frameworks. Rest assured
+you can use your favorite Perl modules with Catalyst.
=over 4
Now http://localhost:3000/hello prints "Hello World!".
-=item * B<Support for CGI, mod_perl, Apache::Request>
+=item * B<Support for CGI, mod_perl, Apache::Request, FastCGI>
-Use L<Catalyst::Engine::Apache> or L<Catalyst::Engine::CGI>.
+Use L<Catalyst::Engine::Apache> or L<Catalyst::Engine::CGI>. Other
+engines are also available.
=back
=item * B<Helper Scripts>
Catalyst provides helper scripts to quickly generate running starter
-code for components and unit tests. See L<Catalyst::Helper>.
+code for components and unit tests. Install L<Catalyst::Devel> and see
+L<Catalyst::Helper>.
=back
=head3 Install
- $ perl -MCPAN -e 'install Task::Catalyst'
+Installation of Catalyst can be a time-consuming and frustrating
+effort, due to its large number of dependencies. The easiest way
+to get up and running is to use Matt Trout's C<cat-install>
+script, from L<http://www.shadowcatsystems.co.uk/static/cat-install>,
+and then install L<Catalyst::Devel>.
+
+ # perl cat-install
+ # perl -MCPAN -e 'install Catalyst::Devel'
=head3 Setup
package MyApp;
use strict;
- use Catalyst qw/-Debug/;
+ use Catalyst qw/-Debug/; # Add other plugins here, e.g.
+ # for session support
MyApp->config(
name => 'My Application',
);
1;
+In older versions of Catalyst, the application class was where you put
+global actions. However, as of version 5.66, the recommended practice is
+to place such actions in a special Root controller (see L</Actions>,
+below), to avoid namespace collisions.
+
=over 4
=item * B<name>
$c->req->cookies->{sessionid};
$c->req->headers->content_type;
$c->req->base;
+ $c->req->uri_with( { page = $pager->next_page } );
=item * L<Catalyst::Response>
$c->stash
$c->stash->{foo} = 'bar';
$c->stash->{baz} = {baz => 'qox'};
- $c->stash->{fred} = [qw/ wilma pebbles/];
+ $c->stash->{fred} = [qw/wilma pebbles/];
and so on.
Note that the stash should be used only for passing data in an
individual request cycle; it gets cleared at a new request. If you need
-to maintain more persistent data, use a session.
+to maintain persistent data, use a session. See
+L<Catalyst::Plugin::Session> for a comprehensive set of
+Catalyst-friendly session-handling tools.
=head3 Actions
-
-
A Catalyst controller is defined by its actions. An action is a
subroutine with a special attribute. You've already seen some examples
of actions in this document. The URL (for example
=item * B<Application Wide Actions>
Actions which are called at the root level of the application
-(e.g. http:///localhost:3000/ ) go in MyApp::Controller::Root, like
+(e.g. http://localhost:3000/ ) go in MyApp::Controller::Root, like
this:
package MyApp::Controller::Root;
}
1;
-
=back
-For most applications, Catalyst requires you to define only one config
-parameter:
-
=head4 Action types
Catalyst supports several types of actions:
explanation of the pre-defined meaning of Catalyst component class
names.
+=item * B<Chained>
+
+Catalyst also provides a method to build and dispatch chains of actions,
+like
+
+ sub catalog : Chained : CaptureArgs(1) {
+ my ( $self, $c, $arg ) = @_;
+ ...
+ }
+
+ sub item : Chained('catalog') : Args(1) {
+ my ( $self, $c, $arg ) = @_;
+ ...
+ }
+
+to handle a C</catalog/*/item/*> path. For extensive information about this
+dispatch type, please see L<Catalyst::DispatchType::Chained>.
+
=item * B<Private>
sub foo : Private { }
=item * B<Args>
-Args is not an action type per se, but an action modifier - it adds a match
-restriction to any action it's provided to, requiring only as many path parts
-as are specified for the action to be valid - for example in
+Args is not an action type per se, but an action modifier - it adds a
+match restriction to any action it's provided to, requiring only as many
+path parts as are specified for the action to be valid - for example in
MyApp::Controller::Foo,
sub bar :Local
individual controllers.
If C<default> isn't acting how you would expect, look at using a
-L</Literal> C<Path> action (with an empty path string). The difference is
-that C<Path> takes arguments relative from the namespace and C<default>
-I<always> takes arguments relative from the root, regardless of what
-controller it's in.
+L</Literal> C<Path> action (with an empty path string). The difference
+is that C<Path> takes arguments relative from the namespace and
+C<default> I<always> takes arguments relative from the root, regardless
+of what controller it's in. Indeed, this is now the recommended way of
+handling default situations; the C<default> private controller should
+be considered deprecated.
=item * B<index : Private>
and C<MyApp::Controller::Catalog::Order::begin> would override this in
turn.
+=item * B<auto : Private>
+
In addition to the normal built-in actions, you have a special action
for making chains, C<auto>. Such C<auto> actions will be run after any
C<begin>, but before your action is processed. Unlike the other
for that URL.
B<Note:> Looking at it another way, C<auto> actions have to return a
-true value to continue processing! You can also C<die> in the autochain
+true value to continue processing! You can also C<die> in the auto
action; in that case, the request will go straight to the finalize
stage, without processing further actions.
$c->res->body( $c->stash->{message} );
}
-A C<forward> does not create a new request, so your request
-object (C<$c-E<gt>req>) will remain unchanged. This is a
-key difference between using C<forward> and issuing a
-redirect.
+A C<forward> does not create a new request, so your request object
+(C<$c-E<gt>req>) will remain unchanged. This is a key difference between
+using C<forward> and issuing a redirect.
You can pass new arguments to a C<forward> by adding them
in an anonymous array. In this case C<$c-E<gt>req-E<gt>args>
Controllers. Catalyst automatically discovers and instantiates them
when you call C<setup> in the main application. All you need to do is
put them in directories named for each Component type. Notice that you
-can use some very terse aliases for each one.
+can use a terse alias for each one.
=over 4
=back
+In older versions of Catalyst, the recommended practice (and the one
+automatically created by helper scripts) was to name the directories
+C<M/>, C<V/>, and C<C/>. Though these still work, we now recommend
+the use of the full names.
+
=head4 Views
To show how to define views, we'll use an already-existing base class for the
You normally render templates at the end of a request, so it's a perfect
use for the global C<end> action.
+In practice, however, you would use a default C<end> action as supplied
+by L<Catalyst::Action::RenderView>.
+
Also, be sure to put the template under the directory specified in
-C<$c-E<gt>config-E<gt>{root}>, or you'll be forced to look at our
-eyecandy debug screen. ;)
+C<$c-E<gt>config-E<gt>{root}>, or you'll end up looking at the debug
+screen.
=head4 Models
$c->stash->{template} = 'list.tt';
- use Some::Outside::DBIC::Module;
- my @records = Some::Outside::DBIC::Module->search({
- artist => 'sri',
+ use Some::Outside::Database::Module;
+ my @records = Some::Outside::Database::Module->search({
+ artist => 'Led Zeppelin',
});
$c->stash->{records} = \@records;
sub new_password : Action { }
sub sign_out : Action { }
+=head3 Models
+
+Models are providers of data. This data could come from anywhere - a
+search engine index, a database table, etc. Typically the data source
+does not have much to do with web applications or Catalyst - it could be
+used to write an offline report generator or a command line tool just
+the same.
+
+The common approach to writing a Catalyst-style model for your
+application is wrapping a generic model (e.g. L<DBIx::Class::Schema>, a
+bunch of XMLs, or anything really) with an object that contains
+configuration data, convenience methods, and so forth.
+
+#### editor: move this part to =head3 Components somehow, right after this
+#### section - this will require deeply rephrasing this paragraph.
+
+Technically, within Catalyst a model is a B<component> - an instance of
+the model's class belonging to the application. It is important to
+stress that the lifetime of these objects is per application, not per
+request.
+
+While the model base class (L<Catalyst::Model>) provides things like
+C<config> and stuff to better integrate the model into the application,
+sometimes this is not enough, and the model requires access to C<$c>
+itself.
+
+Situations where this need might arise include:
+
+=over 4
+
+=item *
+
+Interacting with another model
+
+=item *
+
+Using per-request data to control behavior
+
+=item *
+
+Using plugins in (for example L<Catalyst::Plugin::Cache>).
+
+=back
+
+From a style perspective usually it's bad to make your model "too smart"
+about things - it should worry about business logic and leave the
+integration details to the controllers. If, however, you find that it
+does not make sense at all to use an auxillary controller around the
+model, and the model's need to access C<$c> cannot be sidestepped, there
+exists a power tool called C<ACCEPT_CONTEXT>.
+
+#### editor note: this part is "generic" - it also applies to views and
+#### controllers.
+
+=head3 ACCEPT_CONTEXT
+
+Whenever you call $c->component("Foo") you get back an object - the
+instance of the model. If the component supports the C<ACCEPT_CONTEXT>
+method instead of returning the model itself, the return value of C<<
+$model->ACCEPT_CONTEXT( $c ) >> will be used.
+
+This means that whenever your model/view/controller needs to talk to C<$c> it
+gets a chance to do this when it's needed.
+
+A typical C<ACCEPT_CONTEXT> method will either clone the model and return one
+with the context object set, or it will return a thin wrapper that contains
+C<$c> and delegates to the per-application model object.
+
+A typical C<ACCEPT_CONTEXT> method could look like this:
+
+ sub ACCEPT_CONTEXT {
+ my ( $self, $c, @extra_arguments ) = @_;
+ bless { %$self, c => $c }, ref($self);
+ }
+
+effectively treating $self as a B<prototype object> that gets a new parameter.
+C<@extra_arguments> comes from any trailing arguments to
+C<< $c->component( $bah, @extra_arguments ) >> (or C<< $c->model(...) >>,
+C<< $c->view(...) >> etc).
+
+The life time of this value is B<per usage>, and not per request. To make this
+per request you can use the following technique:
+
+Add a field to C<$c>, like C<my_model_instance>. Then write your
+C<ACCEPT_CONTEXT> method to look like this:
+
+ sub ACCEPT_CONTEXT {
+ my ( $self, $c ) = @_;
+
+ if ( my $per_request = $c->my_model_instance ) {
+ return $per_request;
+ } else {
+ my $new_instance = bless { %$self, c => $c }, ref($self);
+ Scalar::Util::weaken($new_instance->{c}); # or we have a circular reference
+ $c->my_model_instance( $new_instance );
+ return $new_instance;
+ }
+ }
+
+
=head3 Testing
-Catalyst has a built-in http server for testing! (Later, you can easily
-use a more powerful server, e.g. Apache/mod_perl, in a production
-environment.)
+Catalyst has a built-in http server for testing. (Later, you can easily
+use a more powerful server, e.g. Apache/mod_perl or FastCGI, in a
+production environment.)
Start your application on the command line...
Jesse Sheidlower, C<jester@panix.com>
Danijel Milicevic, C<me@danijel.de>
Kieren Diment, C<kd@totaldatasolution.com>
+Yuval Kogman, C<nothingmuch@woobling.org>
=head1 COPYRIGHT