$c->forward('foo');
See L</Flow Control> for a full explanation of C<forward>. Note that, as
-discussed there, when forwarding from another component, you must use the
-absolute path to the method, so that a private C<bar> method in your
-C<MyApp::Controller::Catalog::Order::Process> controller must, if called from
-elsewhere, be reach with C<$c-E<gt>forward('/catalog/order/process/bar')>.
+discussed there, when forwarding from another component, you must use
+the absolute path to the method, so that a private C<bar> method in your
+C<MyApp::Controller::Catalog::Order::Process> controller must, if called
+from elsewhere, be reached with
+C<$c-E<gt>forward('/catalog/order/process/bar')>.
=back
=head4 Built-in Private Actions
-In response to specific application states, Catalyst will automatically call
-these built-in private actions:
+In response to specific application states, Catalyst will automatically
+call these built-in private actions in your application class:
=over 4
=item * B<default : Private>
-Called when no other action matches.
+Called when no other action matches. Could be used, for example, for
+displaying a generic frontpage for the main app, or an error page for
+individual controllers.
=item * B<begin : Private>
-Called at the beginning of a request, before any matching actions are called.
+Called at the beginning of a request, before any matching actions are
+called.
=item * B<end : Private>
-=back
-
Called at the end of a request, after all matching actions are called.
-=head4 B<Built-in actions in controllers/autochaining>
+=back
+
+=head4 Built-in actions in controllers/autochaining
Package MyApp::C::Foo;
sub begin : Private { }
sub default : Private { }
-
-You can define the Built-in Private Actions within your controllers as
-well. The actions will override the ones in lower level controllers or
-your global application.
-
-In addition to the normal built-ins, you have a special action for
-making inheritance chains, 'auto'. These will be run after C<begin>,
-but before your action is processed.
+ sub auto : Private { }
+
+You can define built-in private actions within your controllers as
+well. The actions will override the ones in less-specific controllers,
+or your application class. In other words, for each of the three
+built-in private actions, only one will be run in any request
+cycle. Thus, if C<MyApp::C::Catalog::begin> exists, it will be run in
+place of C<MyApp::begin> if you're in the C<catalog> namespace, and
+C<MyApp::C::Catalog::Order::begin> would override this in turn.
+
+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
+built-ins, C<auto> actions I<do not> override each other; they will be
+called in turn, starting with the application class and going through to
+the I<most> specific class. I<This is the reverse of the order in which
+the normal built-ins override each other>.
+
+Here are some examples of the order in which the various built-ins
+would be called:
=over 4
-=item for a request for /foo/foo
+=item for a request for C</foo/foo>
MyApp::begin
MyApp::auto
- MyApp::C::Foo::default
+ MyApp::C::Foo::default # in the absence of MyApp::C::Foo::Foo
MyApp::end
-=item for a request for /foo/bar/foo
+=item for a request for C</foo/bar/foo>
MyApp::C::Foo::Bar::begin
MyApp::auto
MyApp::C::Foo::auto
- MyApp::C::Foo::Bar::default
+ MyApp::C::Foo::Bar::auto
+ MyApp::C::Foo::Bar::default # for MyApp::C::Foo::Bar::foo
MyApp::C::Foo::Bar::end
=back
-Also, if you need to break out of the chain in one of your auto
-actions, you can return 0, if so, your action will not be processed,
-but the end will, so for the request above, if the first auto returns
-false, it would look like this:
+The C<auto> action is also distinguished by the fact that you can break
+out of the processing chain by returning 0. If an C<auto> action returns
+0, any remaining actions will be skipped, except for C<end>. So, for the
+request above, if the first auto returns false, the chain would look
+like this:
=over 4
-=item for a request for /foo/bar/foo where auto returns false
+=item for a request for C</foo/bar/foo> where first C<auto> returns
+false
MyApp::C::Foo::Bar::begin
MyApp::auto
=back
-B<Note:> auto actions have to return a true value to continue
-processing! You can also die in the autochain action, in that case, the
-request will go straight to the finalize stage, without processing
-further actions.
+An example of why one might use this is an authentication action: you
+could set up a C<auto> action to handle authentication in your
+application class (which will always be called first), and if
+authentication fails, returning 0 would skip any remaining methods
+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
+action; in that case, the request will go straight to the finalize
+stage, without processing further actions.
-=head4 B<URL Argument Handling>
+=head4 URL Path Handling
-If you want to pass variable arguments at the end of a URL, you must use regex
-actions keys with '^' and '$' anchors, and the arguments must be separated with
-forward slashes (/) in the URL. For example, suppose you want to handle
-/foo/$bar/$baz, where $bar and $baz may vary:
+You can pass variable arguments as part of the URL path. In this case,
+you must use regex action keys with '^' and '$' anchors, and the
+arguments must be separated with forward slashes (/) in the URL. For
+example, suppose you want to handle C</foo/$bar/$baz>, where C<$bar> and
+C<$baz> may vary:
sub foo : Regex('^foo$') { my ($self, $context, $bar, $baz) = @_; }
-But what if you also defined actions for /foo/boo and /foo/boo/hoo ?
+But what if you also defined actions for C</foo/boo> and C</foo/boo/hoo>?
sub boo : Path('foo/boo') { .. }
sub hoo : Path('foo/boo/hoo') { .. }
/foo/boo/hoo
/foo/boo
- /foo # might be /foo/bar/baz
+ /foo # might be /foo/bar/baz but won't be /foo/boo/hoo
-So Catalyst would never mistakenly dispatch the first two URLs to the '^foo$' action.
+So Catalyst would never mistakenly dispatch the first two URLs to the
+'^foo$' action.
-=head4 B<Parameter Processing>
+=head4 Parameter Processing
-Parameters are handled with methods in the L<Catalyst::Request>
-class. The C<param> method is functionally equivalent to the C<param>
-method of C<CGI.pm> and can be used in modules that require this.
+Parameters passed in the URL query string are handled with methods in
+the L<Catalyst::Request> class. The C<param> method is functionally
+equivalent to the C<param> method of C<CGI.pm> and can be used in
+modules that require this.
# http://localhost:3000/catalog/view/?category=hardware&page=3
my $category = $c->req->param('category');
=head3 Flow Control
-You control the application flow with the C<forward> method, which accepts the
-key of an action to execute. A forward is like a method call, only it wraps the
-call in an eval to allow exception handling, and to pass along the context object,
-and allow profiling of each method.
+You control the application flow with the C<forward> method, which
+accepts the key of an action to execute. This can be an action in the
+same or another Catalyst controller, or a Class name, optionally
+followed by a method name. After a C<forward>, the control flow will
+return to the method from which the C<forward> was issued.
+
+A C<forward> is similar to a method call. The main differences are that
+it wraps the call in an C<eval> to allow exception handling; it
+automatically passes along the context object (C<$c> or C<$context>);
+and it allows profiling of each call (displayed in the log with
+debugging enabled).
sub hello : Global {
my ( $self, $c ) = @_;
$c->stash->{message} = 'Hello World!';
- $c->forward('check_message');
+ $c->forward('check_message'); # $c is automatically included
}
sub check_message : Private {
$c->res->output( $c->stash->{message} );
}
-As opposed to a redirect, your request object will remain unchanged, as no actual
-new request is started, unless you pass along new args like this:
+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>
+will be changed for the duration of the C<forward> only; upon
+return, the original value of C<$c-E<gt>req-E<gt>args> will
+be reset.
sub hello : Global {
my ( $self, $c ) = @_;
$c->stash->{message} = 'Hello World!';
- $c->forward('check_message',[qw/test1/);
+ $c->forward('check_message',[qw/test1/]);
+ # now $c->req->args is back to what it was before
}
-In that case, $c->request->argumentss will be changed until you return from the
-forward. test1 will also be passed as an argument to check_message after $c.
+ sub check_message : Private {
+ my ( $self, $c ) = @_;
+ my $first_argument = $c->req->args[0]; # now = 'test1'
+ # do something...
+ }
-As you can see from these examples, you can just use the method name as long as
-you are referring to methods in the same controller. If you want to forward to a
-method in another controller, or the main application, you will have to refer to
-the method by absolute path.
+As you can see from these examples, you can just use the method name as
+long as you are referring to methods in the same controller. If you want
+to forward to a method in another controller, or the main application,
+you will have to refer to the method by absolute path.
$c->forward('/my/controller/action');
- $c->forward('/default');
+ $c->forward('/default'); # calls default in main application
-You can also forward to classes and methods.
+Here are some examples of how to forward to classes and methods.
sub hello : Global {
my ( $self, $c ) = @_;
sub bye : Global {
my ( $self, $c ) = @_;
- $c->forward('MyApp::M::Hello');
+ $c->forward('MyApp::M::Hello'); # no method: will try 'process'
}
package MyApp::M::Hello;
$c->res->output('Goodbye World!');
}
-Note that C<forward> returns to the calling action and continues processing
-after the action finishes. Catalyst will automatically try to call process() if
-you omit the method.
+Note that C<forward> returns to the calling action and continues
+processing after the action finishes. If you want all further processing
+in the calling action to stop, use C<detach> instead, which will execute
+the C<detach>ed action and not return to the calling sub. In both cases,
+Catalyst will automatically try to call process() if you omit the
+method.
=head3 Components
1;
-You don't have to C<use> or otherwise register Models, Views, and 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.
+You don't have to C<use> or otherwise register Models, Views, and
+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.
=over 4
script/myapp_create.pl view TT TT
-where the first C<TT> tells the script to create a Template Toolkit
-view, and the second tells the script that its name should be C<TT>.)
+where the first C<TT> tells the script that the name of the view should
+be C<TT>, and the second that it should be a Template Toolkit view.)
This gives us a process() method and we can now just do
$c->forward('MyApp::V::TT') to render our templates. The base class makes
$c->forward('MyApp::V::TT');
}
-You normally render templates at the end of a request, so it's a perfect use for
-the global C<end> action.
+You normally render templates at the end of a request, so it's a perfect
+use for the global C<end> action.
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 be forced to look at our
+eyecandy debug screen. ;)
=head4 Models
1;
+ # Then, in a TT template:
The id is [% item.data %]
+Models do not have to be part of your Catalyst application; you
+can always call an outside module that serves as your Model:
+
+ # in a Controller
+ sub list : Local {
+ my ( $self, $c ) = @_;
+ $c->stash->{template} = 'list.tt';
+ use Some::Outside::CDBI::Module;
+ my @records = Some::Outside::CDBI::Module->retrieve_all;
+ $c->stash->{records} = \@records;
+ }
+
+But by using a Model that is part of your Catalyst application, you gain
+several things: you don't have to C<use> each component, Catalyst will
+find and load it automatically at compile-time; you can C<forward> to
+the module, which can only be done to Catalyst componenents; and only
+Catalyst components can be fetched with
+C<$c-E<gt>comp('MyApp::M::SomeModel')>.
+
+Happily, since many people have existing Model classes that they
+would like to use with Catalyst (or, conversely, they want to
+write Catalyst models that can be used outside of Catalyst, e.g.
+in a cron job), it's trivial to write a simple component in
+Catalyst that slurps in an outside Model:
+
+ package MyApp::M::Catalog;
+ use base qw/Catalyst::Base Some::Other::CDBI::Module::Catalog/;
+ 1;
+
+and that's it! Now C<Some::Other::CDBI::Module::Catalog> is part of your
+Cat app as C<MyApp::M::Catalog>.
+
=head4 Controllers
Multiple controllers are a good way to separate logical domains of your
package MyApp::C::Login;
- sign-in : Local { }
- new-password : Local { }
- sign-out : Local { }
+ sub sign-in : Local { }
+ sub new-password : Local { }
+ sub sign-out : Local { }
package MyApp::C::Catalog;