X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Manual.git;a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FCookbook.pod;h=ca49cf3c534b30be4743512db943531e855dedc1;hp=75bae02494968e719d0d357caa1f8a8025305a8e;hb=23cf3a36a43f0eb257f9438491a8444049ebdec8;hpb=ca7528dfa8625d0ed6688f2bb93372ab3d958881 diff --git a/lib/Catalyst/Manual/Cookbook.pod b/lib/Catalyst/Manual/Cookbook.pod index 75bae02..ca49cf3 100644 --- a/lib/Catalyst/Manual/Cookbook.pod +++ b/lib/Catalyst/Manual/Cookbook.pod @@ -62,11 +62,10 @@ nifty statistics in your debug messages. =head2 Enable debug status in the environment Normally you enable the debugging info by adding the C<-Debug> flag to -your C statement (or C<__PACKAGE__->setup(qw/-Debug/) -). 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 or CMYAPPE_DEBUG> to a -true value. +your C 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 or +CMYAPPE_DEBUG> to a true value. =head2 Sessions @@ -114,11 +113,11 @@ reference. =head3 EXAMPLE use parent qw/Catalyst/; - __PACKAGE__->setup( qw/ + use Catalyst qw/ Session Session::Store::FastMmap Session::State::Cookie - /;) + /; ## Write data into the session @@ -269,12 +268,11 @@ The L plugin is required when implementing roles: use parent qw/Catalyst/; - __PACKAGE__->setup (qw/ + use Catalyst qw/ Authentication Authentication::Credential::Password Authentication::Store::Htpasswd - Authorization::Roles - /); + Authorization::Roles/; Roles are implemented automatically when using L: @@ -404,10 +402,10 @@ the user is a member. =head3 EXAMPLE use parent qw/Catalyst/; - __PACKAGE__->setup( qw/Authentication - Authentication::Credential::Password - Authentication::Store::Htpasswd - Authorization::Roles/); + use Catalyst qw/Authentication + Authentication::Credential::Password + Authentication::Store::Htpasswd + Authorization::Roles/; __PACKAGE__->config->{authentication}{htpasswd} = "passwdfile"; @@ -501,10 +499,10 @@ The Authorization::Roles plugin let's us perform role based access control checks. Let's load it: use parent qw/Catalyst/; - __PACKAGE__->setup(qw/ - Authentication # yadda yadda - Authorization::Roles - /); + use Catalyst qw/ + Authentication # yadda yadda + Authorization::Roles + /; And now our action should look like this: @@ -718,7 +716,7 @@ later) and SOAP::Lite (for XMLRPCsh.pl). 3. Add the XMLRPC plugin to MyApp.pm - __PACKAGE__->setup( qw/-Debug Static::Simple XMLRPC/); + use Catalyst qw/-Debug Static::Simple XMLRPC/; 4. Add an API controller @@ -1197,6 +1195,8 @@ becomes http://localhost:3000/handles +See also: L + =item Local When using a Local attribute, no parameters are needed, instead, the @@ -1238,6 +1238,8 @@ and etc. +See also: L + =item LocalRegex A LocalRegex is similar to a Regex, except it only matches below the current @@ -1255,6 +1257,11 @@ and etc. +=item Chained + +See L for a description of how the chained +dispatch type works. + =item Private Last but not least, there is the Private attribute, which allows you @@ -1362,6 +1369,71 @@ L L +=head2 DRY Controllers with Chained actions. + +Imagine that you would like the following paths in your application: + +=over + +=item B/track/> + +Displays info on a particular track. + +In the case of a multi-volume CD, this is the track sequence. + +=item B/volume//track/> + +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. @@ -1468,6 +1540,12 @@ the Catalyst Request object: (See the L Flow_Control section for more information on passing arguments via C.) +=head2 Chained dispatch using base classes, and inner packages. + + package MyApp::Controller::Base; + use base qw/Catalyst::Controller/; + + sub key1 : Chained('/') =head1 Deployment @@ -1699,6 +1777,9 @@ can be used without worrying about the thread safety of your application. =head3 Cons +You may have to disable mod_deflate. If you experience page hangs with +mod_fastcgi then remove deflate.load and deflate.conf from mods-enabled/ + =head4 More complex environment With FastCGI, there are more things to monitor and more processes running @@ -1768,7 +1849,7 @@ The development server is a mini web server written in perl. If you 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 for this kind of deployment instead, since +L 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. @@ -1813,9 +1894,18 @@ Make sure mod_proxy is enabled and add: Order deny,allow Allow from all + + # 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. @@ -1903,7 +1993,7 @@ B is found and served. Using the plugin is as simple as setting your use line in MyApp.pm to include: - __PACKAGE__->setup( qw/Static::Simple/); + use Catalyst qw/Static::Simple/; and already files will be served. @@ -1988,7 +2078,7 @@ using L. In your main application class (MyApp.pm), load the plugin: - __PACKAGE__->setup( qw/-Debug FormValidator Static OtherPlugin/); + use Catalyst qw/-Debug FormValidator Static OtherPlugin/; You will also need to make sure your end method does I forward static content to the view, perhaps like this: @@ -2103,7 +2193,7 @@ 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. - __PACKAGE__->setup( qw/Cache::FileCache/); + use Catalyst qw/Cache::FileCache/; ... @@ -2151,7 +2241,7 @@ thing for every single user who views the page. We can add the PageCache plugin to speed things up. - __PACKAGE__->setup( qw/Cache::FileCache PageCache/); + use Catalyst qw/Cache::FileCache PageCache/; sub front_page : Path ('/') { my ( $self, $c ) = @_;