I<initially> simpler to use, 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. For
-example, this leads to Catalyst being more suited to system integration
+example, this leads to Catalyst being better suited to system integration
tasks than other web frameworks.
=head3 MVC
=item * B<Controller>
Control the whole request phase, check parameters, dispatch actions, flow
-control. Catalyst itself!
+control. This is the meat of where Catalyst works.
=back
Now http://localhost:3000/hello prints "Hello World!".
-Note that actions with the C< :Global > attribute are equivalent to
+Note that actions with the C< :Local > attribute are equivalent to
using a C<:Path('action_name') > attribute, so our action could be
equivalently:
ready server (although you'll probably want to run it behind a front end proxy
if you end up using it).
+=item * PSGI Support
+
+Starting with Catalyst version 5.9 Catalyst ships with L<PSGI> integration
+for even more powerful and flexible testing and deployment options. See
+L<Catalyst::PSGI> for details.
+
=back
=head3 Simplicity
script/myapp_create.pl model MyModel DBIC::Schema MySchema create=static 'dbi:SQLite:/tmp/myapp.db'
-L<DBIx::Class::Schema::Loader> can automaticall load table layouts and
+L<DBIx::Class::Schema::Loader> can automatically load table layouts and
relationships, and convert them into a static schema definition
C<MySchema>, which you can edit later.
found, and automatically call the actions it finds that match the
circumstances of the request.
-The URL (for example http://localhost.3000/foo/bar) consists of two
+The URL (for example http://localhost:3000/foo/bar) consists of two
parts, the base, describing how to connect to the server
(http://localhost:3000/ in this example) and the path, which the
server uses to decide what to return (foo/bar). Please note that the
=item * B<Overriding the namespace>
-Note that __PACKAGE__->config->{namespace} can be used to override the
+Note that I<< __PACKAGE__->config->(namespace => ... ) >> can be used to override the
current namespace when matching. So:
package MyApp::Controller::Example;
would normally use 'example' as its namespace for matching, but if
this is specially overridden with
- __PACKAGE__->config->{namespace}='thing';
+ __PACKAGE__->config( namespace => 'thing' );
it matches using the namespace 'thing' instead.
package MyApp::Controller::Root;
use base 'Catalyst::Controller';
+
# Sets the actions in this controller to be registered with no prefix
# so they function identically to actions created in MyApp.pm
- __PACKAGE__->config->{namespace} = '';
+
+ __PACKAGE__->config( namespace => '');
+
sub default : Path {
my ( $self, $context ) = @_;
$context->response->status(404);
$context->response->body('404 not found');
}
+
1;
The code
- __PACKAGE__->config->{namespace} = '';
+ __PACKAGE__->config( namespace => '' );
makes the controller act as if its namespace is empty. As you'll see
-below, an empty namespace makes many of the URL-matching attributes,
-such as :Path, :Local and :Global matches, match at the start of the
-URL path.
+below, an empty namespace makes many of the URL-matching attributes, such
+as :Path and :Local match at the start of the URL path (i.e. the
+application root).
=back
Matches any URL beginning with> http://localhost:3000/my/controller/foo. The namespace and
subroutine name together determine the path.
-=item * Namespace-level (C<:Global>)
+=item * Root-level (C<:Global>)
package MyApp::Controller::Foo;
- sub foo : Global { }
-Matches http://localhost:3000/foo - that is, the action is mapped
-directly to the controller namespace, ignoring the function name.
+ sub bar : Global {
+ my ($self, $c) = @_;
+ $c->res->body(
+ $c->res->body('sub bar in Controller::Foo triggered on a request for '
+ . $c->req->uri));
+ }
-C<:Global> is equivalent C<:Local> one level higher in
-the namespace.
+1;
- package MyApp::Controller::Root;
- __PACKAGE__->config->{namespace}='';
- sub foo : Local { }
+Matches http://localhost:3000/bar - that is, the action is mapped
+directly to the method name, ignoring the controller namespace.
-Use whichever makes the most sense for your application.
+C<:Global> always matches from the application root: it is simply
+shorthandfor C<:Path('/methodname')>. C<:Local> is shorthand for
+C<:Path('methodname')>, which takes the controller namespace as described
+above.
+
+Usage of the C<Global> handler is rare in all but very old Catalyst
+applications (e.g. before Catalyst 5.7). The use cases where C<Global>
+used to make sense are now largely replaced by the C<Chained> dispatch
+type, or by empty C<Path> declarations on an controller action. C<Global>
+is still included in Catalyst for backwards compatibility, although
+legitimate use-cases for it may still exist.
=item * Changing handler behaviour: eating arguments (C<:Args>)
match precisely.
No :Args at all means that B<any number> of arguments are taken. Thus, any
-URL that B<starts with> the controller's path will match.
+URL that B<starts with> the controller's path will match. Obviously, this means
+you cannot chain from an action that does not specify args, as the next action
+in the chain will be swallowed as an arg to the first!
=item * Literal match (C<:Path>)
sub auto : Private { }
C<auto>, however, doesn't override like this: providing they exist,
-C<MyApp::auto>, C<MyApp::Controller::Catalog::auto> and
+C<MyApp::Controller::Root::auto>, C<MyApp::Controller::Catalog::auto> and
C<MyApp::Catalog::Order::auto> would be called in turn.
Here are some examples of the order in which the various built-ins
# now $c->req->args is back to what it was before
}
- sub check_message : Private {
- my ( $self, $c ) = @_;
- my $first_argument = $c->req->args->[0]; # now = 'test1'
+ sub check_message : Action {
+ my ( $self, $c, $first_argument ) = @_;
+ my $also_first_argument = $c->req->args->[0]; # now = 'test1'
# do something...
}
$c->forward('/my/controller/action');
$c->forward('/default'); # calls default in main application
-Here are some examples of how to forward to classes and methods.
+You can also forward to classes and methods.
sub hello : Global {
my ( $self, $c ) = @_;
- $c->forward(qw/MyApp::Model::Hello say_hello/);
+ $c->forward(qw/MyApp::View:Hello say_hello/);
}
sub bye : Global {
$c->forward('MyApp::Model::Hello'); # no method: will try 'process'
}
- package MyApp::Model::Hello;
+ package MyApp::View::Hello;
sub say_hello {
my ( $self, $c ) = @_;
$c->res->body('Goodbye World!');
}
+This mechanism is used by L<Catalyst::Action::RenderView> to forward
+to the C<process> method in a view class.
+
+It should be noted that whilst forward is useful, it is not the only way
+of calling other code in Catalyst. Forward just gives you stats in the debug
+screen, wraps the code you're calling in an exception handler and localises
+C<< $c->request->args >>.
+
+If you don't want or need these features then it's perfectly acceptable
+(and faster) to do something like this:
+
+ sub hello : Global {
+ my ( $self, $c ) = @_;
+ $c->stash->{message} = 'Hello World!';
+ $self->check_message( $c, 'test1' );
+ }
+
+ sub check_message {
+ my ( $self, $c, $first_argument ) = @_;
+ # do something...
+ }
+
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
Catalyst will automatically try to call process() if you omit the
method.
-
=head3 Testing
Catalyst has a built-in http server for testing or local