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
=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>
);
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 #####, below),
+to avoid namespace collisions.
+
=over 4
=item * B<name>
whatever you need. You can access them anywhere in your application via
C<$context-E<gt>config-E<gt>{$param_name}>.
+###### We need a short section on configuration here.
+
=head3 Context
Catalyst automatically blesses a Context object into your application
=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:
arguments at the end of your URL, you must use regex action keys. See
L</URL Path Handling> below.
+=item * B<Chained>
+
+ sub section :PathPart('section') :Chained('/') :Captures(1) { }
+
+Chained is a powerful way to handle canonical URIs of the form
+C<http://localhost:3000/section/1/item/2>. Using this URI as an example,
+in Controller::Root you can do the following:
+
+ sub section_handler :PathPart('section') :Chained('/') :Captures(1) {
+ my ( $self, $c ) = @_;
+ $c->stash->{'section'} =
+ $c->Model('Sections')->find($c->req->captures->[0]);
+ }
+
+ sub item_handler :PathPart('item') :Chained('/section_handler') :Args(1) {
+ my ( $self, $c ) = @_;
+ $c->stash->{'item'} =
+ $c->stash->{'section'}->find_related('item',$c->args->[0]);
+ }
+
+The subroutine C<section_handler> matches the path segment "section" as
+a child of "/". It then takes the next path segment, as referenced by
+C<:Captures(1)>, and stashes it in the arrayref
+C<$c-E<gt>req-E<gt>captures>. Since there is also a child of this
+handler, it also gets run, functioning in the same way. However, the
+C<item_handler> subroutine has the C<Args> attribute which means this
+particular routine will only run if there is exactly one argument. See
+L</Args> below for more options.
+
+A parent action can be in any controller or namespace.
+
+Multiple actions can specify the same parent action in their C<Chained>;
+that is, one action can have multiple children.
+
+=item Chained('xyz')
+
+The action of the parent. For instance, if you have a method
+C<item_handler> in the controller C<SuperMarket::Aisle>, the action
+would be C</supermarket/aisle/item_handler>. For a Root handler this
+would be '/'. For an action in the same controller namespace you can use
+a relative name like C<:Chained('foo')>.
+
+=item PathPart('xyz')
+
+The name of this path section in the Chained tree mapping to the URI. If
+you specify C<:PathPart> without arguments, it takes the name of the
+action specifying the argument. For example, these two declarations
+have the same effect:
+
+ sub foo :PathPart('foo') :Chained('bar') :Args(1) {
+ ...
+ }
+
+and
+
+ sub foo :PathPart :Chained('bar') :Args(1) {
+ ...
+ }
+
+The value can also contain a slash, for example:
+
+ sub baz :PathPart('bar/baz') :Chained('/') :Captures(1) {
+ ...
+ }
+
+would be involved in matches on C</bar/baz/*/...> paths.
+
+=item Captures(integer)
+
+Will 'collapse' the next C<integer> path segments in the request URI and
+push them into the arrayref C<$c-E<gt>req-E<gt>captures>. An action
+specifying C<Captures> is thought to be used as target for C<Chained>
+specifications. Also see the C<Args> attribute below, which is used for
+endpoints.
+
+=item Args(int)
+
+The number of path segments to capture at the end of a request URI. This
+B<must> be included in your leaf nodes. You can use C<Args(0)> for an
+equivalent of the index action. Args with no parameters will capture
+every postfixed segment into C<$c-E<gt>req-E<gt>args>.
+
+A specification of C<Args> is seen as endpoint in regard to an additional
+C<Chained> specification.
+
=item * B<Top-level> (B<Global>)
package MyApp::Controller::Foo;
$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
=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>.
+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.
+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.
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 typicall C<ACCEPT_CONTEXT> method could look like this:
+A typical C<ACCEPT_CONTEXT> method could look like this:
sub ACCEPT_CONTEXT {
my ( $self, $c, @extra_arguments ) = @_;
}
-
=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...