=head2 Enable debug status in the environment
Normally you enable the debugging info by adding the C<-Debug> flag to
-your C<use Catalyst> statement. However, you can also enable it using
+your C<use Catalyst> statement . However, you can also enable it using
environment variable, so you can (for example) get debug info without
modifying your application scripts. Just set C<CATALYST_DEBUG> or
C<E<lt>MYAPPE<gt>_DEBUG> to a true value.
=head3 EXAMPLE
- use Catalyst qw/
- Session
- Session::Store::FastMmap
- Session::State::Cookie
- /;
+ use parent qw/Catalyst/;
+ use Catalyst qw/
+ Session
+ Session::Store::FastMmap
+ Session::State::Cookie
+ /;
## Write data into the session
The L<Catalyst::Plugin::Authorization::Roles> plugin is required when
implementing roles:
+ use parent qw/Catalyst/;
use Catalyst qw/
- Authentication
- Authentication::Credential::Password
- Authentication::Store::Htpasswd
- Authorization::Roles
- /;
+ Authentication
+ Authentication::Credential::Password
+ Authentication::Store::Htpasswd
+ Authorization::Roles/;
Roles are implemented automatically when using
L<Catalyst::Authentication::Store::Htpasswd>:
=head3 EXAMPLE
+ use parent qw/Catalyst/;
use Catalyst qw/Authentication
Authentication::Credential::Password
Authentication::Store::Htpasswd
The Authorization::Roles plugin let's us perform role based access
control checks. Let's load it:
+ use parent qw/Catalyst/;
use Catalyst qw/
- Authentication # yadda yadda
- Authorization::Roles
- /;
+ Authentication # yadda yadda
+ Authorization::Roles
+ /;
And now our action should look like this:
http://localhost:3000/handles
+See also: L<Catalyst::DispatchType::Path>
+
=item Local
When using a Local attribute, no parameters are needed, instead, the
etc.
+See also: L<Catalyst::DispatchType::Regex>
+
=item LocalRegex
A LocalRegex is similar to a Regex, except it only matches below the current
etc.
+=item Chained
+
+See L<Catalyst::DispatchType::Chained> for a description of how the chained
+dispatch type works.
+
=item Private
Last but not least, there is the Private attribute, which allows you
L<http://dev.catalyst.perl.org/wiki/FlowChart>
+=head2 DRY Controllers with Chained actions.
+
+Imagine that you would like the following paths in your application:
+
+=over
+
+=item B</cd/<ID>/track/<ID>>
+
+Displays info on a particular track.
+
+In the case of a multi-volume CD, this is the track sequence.
+
+=item B</cd/<ID>/volume/<ID>/track/<ID>>
+
+Displays info on a track on a specific volume.
+
+=back
+
+Here is some example code, showing how to do this with chained controllers:
+
+ package CD::Controller;
+ use base qw/Catalyst::Controller/;
+
+ sub root : Chained('/') PathPart('/cd') CaptureArgs(1) {
+ my ($self, $c, $cd_id) = @_;
+ $c->stash->{cd_id} = $cd_id;
+ $c->stash->{cd} = $self->model('CD')->find_by_id($cd_id);
+ }
+
+ sub trackinfo : Chained('track') PathPart('') Args(0) RenderView {
+ my ($self, $c) = @_;
+ }
+
+ package CD::Controller::ByTrackSeq;
+ use base qw/CD::Controller/;
+
+ sub track : Chained('root') PathPart('track') CaptureArgs(1) {
+ my ($self, $c, $track_seq) = @_;
+ $c->stash->{track} = $self->stash->{cd}->find_track_by_seq($track_seq);
+ }
+
+ package CD::Controller::ByTrackVolNo;
+ use base qw/CD::Controller/;
+
+ sub volume : Chained('root') PathPart('volume') CaptureArgs(1) {
+ my ($self, $c, $volume) = @_;
+ $c->stash->{volume} = $volume;
+ }
+
+ sub track : Chained('volume') PathPart('track') CaptureArgs(1) {
+ my ($self, $c, $track_no) = @_;
+ $c->stash->{track} = $self->stash->{cd}->find_track_by_vol_and_track_no(
+ $c->stash->{volume}, $track_no
+ );
+ }
+
+Note that adding other actions (i.e. chain endpoints) which operate on a track
+is simply a matter of adding a new sub to CD::Controller - no code is duplicated,
+even though there are two different methods of looking up a track.
+
+This technique can be expanded as needed to fulfil your requirements - for example,
+if you inherit the first action of a chain from a base class, then mixing in a
+different base class can be used to duplicate an entire URL hieratchy at a different
+point within your application.
+
=head2 Component-based Subrequests
See L<Catalyst::Plugin::SubRequest>.
(See the L<Catalyst::Manual::Intro> Flow_Control section for more
information on passing arguments via C<forward>.)
+=head2 Chained dispatch using base classes, and inner packages.
+
+ package MyApp::Controller::Base;
+ use base qw/Catalyst::Controller/;
+
+ sub key1 : Chained('/')
=head1 Deployment
expect a low number of hits or you don't need mod_perl/FastCGI speed,
you could use the development server as the application server with a
lightweight proxy web server at the front. However, consider using
-L<Catalyst::Engine::HTTP::POE> for this kind of deployment instead, since
+L<Catalyst::Engine::HTTP::Prefork> for this kind of deployment instead, since
it can better handle multiple concurrent requests without forking, or can
prefork a set number of servers for improved performance.
Order deny,allow
Allow from all
</Proxy>
+
+ # Need to specifically stop these paths from being passed to proxy
+ ProxyPass /static !
+ ProxyPass /favicon.ico !
+
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
+ # This is optional if you'd like to show a custom error page
+ # if the proxy is not available
+ ErrorDocument 502 /static/error_pages/http502.html
+
You can wrap the above within a VirtualHost container if you want
different apps served on the same host.
Cache::FastMmap, Cache::FileCache, and Cache::Memcached. These can be
used to cache the result of slow operations.
-This very page you're viewing makes use of the FileCache plugin to cache the
+The Catalyst Advent Calendar uses the FileCache plugin to cache the
rendered XHTML version of the source POD document. This is an ideal
-application for a cache because the source document changes infrequently but
-may be viewed many times.
+application for a cache because the source document changes
+infrequently but may be viewed many times.
use Catalyst qw/Cache::FileCache/;