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.
+to place such actions in a special Root controller (see L</Actions>,
+below), to avoid namespace collisions.
=over 4
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
$c->req->cookies->{sessionid};
$c->req->headers->content_type;
$c->req->base;
+ $c->req->uri_with( { page = $pager->next_page } );
=item * L<Catalyst::Response>
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
arguments at the end of your URL, you must use regex action keys. See
L</URL Path Handling> below.
-=item * B<ChildOf>
-
- sub section :PathPart('section') :ChildOf('/') :Captures(1) { }
-
-ChildOf 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') :ChildOf('/') :Captures(1) {
- my ( $self, $c ) = @_;
- $c->stash->{'section'} =
- $c->Model('Sections')->find($c->req->captures->[0]);
- }
-
- sub item_handler :PathPart('item') :ChildOf('/section') :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<ChildOf>;
-that is, one action can have multiple children.
-
-=item ChildOf('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<:ChildOf('foo')>.
-
-=item PathPart('xyz')
-
-The name of this path section in the ChildOf 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') :ChildOf('bar') :Args(1) {
- ...
- }
-
-and
-
- sub foo :PathPart :ChildOf('bar') :Args(1) {
- ...
- }
-
-The value can also contain a slash, for example:
-
- sub baz :PathPart('bar/baz') :ChildOf('/') :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<ChildOf>
-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<ChildOf> specification.
-
=item * B<Top-level> (B<Global>)
package MyApp::Controller::Foo;
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 foo : Chained : CaptureArgs(1) {
+ my ( $self, $c, $arg ) = @_;
+ ...
+ }
+
+ sub bar : Chained('foo') : Args(1) {
+ my ( $self, $c, $arg ) = @_;
+ ...
+ }
+
+to handle a C</foo/*/bar/*> path. For extensive information about this
+dispatch type, please see L<Catalyst::DispatchType::Chained>.
+
=item * B<Private>
sub foo : Private { }
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>
}
You normally render templates at the end of a request, so it's a perfect
-use for the global C<end> action.
+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;
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;
- }
- }
+ 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