Spelling fixes throughout core modules
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Cookbook.pod
1 =head1 NAME
2
3 Catalyst::Manual::Cookbook - Cooking with Catalyst
4
5 =head1 DESCRIPTION
6
7 Yummy code like your mum used to bake!
8
9 =head1 RECIPES
10
11 =head2 Force debug screen
12
13 You can force Catalyst to display the debug screen at the end of the request by
14 placing a C<die()> call in the C<end> action.
15
16      sub end : Private {
17          my ( $self, $c ) = @_;
18          die "forced debug";
19      }
20
21 If you're tired of removing and adding this all the time, you can add a
22 condition in the C<end> action. For example:
23
24     sub end : Private {  
25         my ( $self, $c ) = @_;  
26         die "forced debug" if $c->req->params->{dump_info};  
27     }  
28
29 Then just add to your query string C<"&dump_info=1">, or the like, to
30 force debug output.
31
32
33 =head2 Disable statistics
34
35 Just add this line to your application class if you don't want those nifty
36 statistics in your debug messages.
37
38     sub Catalyst::Log::info { }
39
40 =head2 Scaffolding
41
42 Scaffolding is very simple with Catalyst.
43 Just use Catalyst::Model::CDBI::CRUD as your base class.
44
45     # lib/MyApp/Model/CDBI.pm
46     package MyApp::Model::CDBI;
47
48     use strict;
49     use base 'Catalyst::Model::CDBI::CRUD';
50
51     __PACKAGE__->config(
52         dsn           => 'dbi:SQLite:/tmp/myapp.db',
53         relationships => 1
54     );
55
56     1;
57
58     # lib/MyApp.pm
59     package MyApp;
60
61     use Catalyst 'FormValidator';
62
63     __PACKAGE__->config(
64         name => 'My Application',
65         root => '/home/joeuser/myapp/root'
66     );
67
68     sub my_table : Global {
69         my ( $self, $c ) = @_;
70         $c->form( optional => [ MyApp::Model::CDBI::Table->columns ] );
71         $c->forward('MyApp::Model::CDBI::Table');
72     }
73
74     1;
75
76 Modify the C<$c-E<gt>form()> parameters to match your needs, and don't
77 forget to copy the templates into the template root. Can't find the
78 templates?  They were in the CRUD model distribution, so you can do
79 B<look Catalyst::Model::CDBI::CRUD> from the CPAN shell to find them.
80
81 Other Scaffolding modules are in development at the time of writing.
82
83 =head2 File uploads
84
85 =head3 Single file upload with Catalyst
86
87 To implement uploads in Catalyst, you need to have a HTML form similar to
88 this:
89
90     <form action="/upload" method="post" enctype="multipart/form-data">
91       <input type="hidden" name="form_submit" value="yes">
92       <input type="file" name="my_file">
93       <input type="submit" value="Send">
94     </form>
95
96 It's very important not to forget C<enctype="multipart/form-data"> in
97 the form.
98
99 Catalyst Controller module 'upload' action:
100
101     sub upload : Global {
102         my ($self, $c) = @_;
103
104         if ( $c->request->parameters->{form_submit} eq 'yes' ) {
105
106             if ( my $upload = $c->request->upload('my_file') ) {
107             
108                 my $filename = $upload->filename;
109                 my $target   = "/tmp/upload/$filename";
110                 
111                 unless ( $upload->link_to($target) || $upload->copy_to($target) ) {
112                     die( "Failed to copy '$filename' to '$target': $!" );
113                 }
114             }
115         }
116         
117         $c->stash->{template} = 'file_upload.html';
118     }
119
120 =head3 Multiple file upload with Catalyst
121
122 Code for uploading multiple files from one form needs a few changes:
123
124 The form should have this basic structure:
125
126     <form action="/upload" method="post" enctype="multipart/form-data">
127       <input type="hidden" name="form_submit" value="yes">
128       <input type="file" name="file1" size="50"><br>
129       <input type="file" name="file2" size="50"><br>
130       <input type="file" name="file3" size="50"><br>
131       <input type="submit" value="Send">
132     </form>
133
134 And in the controller:
135
136     sub upload : Local {
137         my ($self, $c) = @_;
138
139         if ( $c->request->parameters->{form_submit} eq 'yes' ) {
140
141             for my $field ( $c->req->upload ) {
142
143                 my $upload   = $c->req->upload($field);
144                 my $filename = $upload->filename;
145                 my $target   = "/tmp/upload/$filename";
146                 
147                 unless ( $upload->link_to($target) || $upload->copy_to($target) ) {
148                     die( "Failed to copy '$filename' to '$target': $!" );
149                 }
150             }
151         }
152
153         $c->stash->{template} = 'file_upload.html';
154     }
155
156 C<for my $field ($c-E<gt>req->upload)> loops automatically over all file
157 input fields and gets input names. After that is basic file saving code,
158 just like in single file upload.
159
160 Notice: C<die>ing might not be what you want to do, when an error
161 occurs, but it works as an example. A better idea would be to store
162 error C<$!> in $c->stash->{error} and show a custom error template
163 displaying this message.
164
165 For more information about uploads and usable methods look at
166 L<Catalyst::Request::Upload> and L<Catalyst::Request>.
167
168 =head2 Authentication with Catalyst::Plugin::Authentication::CDBI
169
170 There are (at least) two ways to implement authentication with this plugin:
171 1) only checking username and password;
172 2) checking username, password, and the roles the user has
173
174 For both variants you'll need the following code in your MyApp package:
175
176     use Catalyst qw/Session::FastMmap Static Authentication::CDBI/;
177
178     MyApp->config( authentication => { user_class => 'MyApp::M::MyApp::Users',
179                                        user_field => 'email',
180                                        password_field => 'password' });
181
182 'user_class' is a Class::DBI class for your users table.
183 'user_field' tells which field is used for username lookup (might be 
184 email, first name, surname etc.).
185 'password_field' is, well, password field in your table and by default 
186 password is stored in plain text. Authentication::CDBI looks for 'user' 
187 and 'password' fields in table, if they're not defined in the config.
188
189 In PostgreSQL, the users table might be something like:
190
191  CREATE TABLE users (
192    user_id   serial,
193    name      varchar(100),
194    surname   varchar(100),
195    password  varchar(100),
196    email     varchar(100),
197    primary key(user_id)
198  );
199
200 We'll discuss the first variant for now:
201 1. user:password login/auth without roles
202
203 To log in a user you might use an action like this:
204
205     sub login : Local {
206         my ($self, $c) = @_;
207         if ($c->req->params->{username}) {
208             $c->session_login($c->req->params->{username}, 
209                               $c->req->params->{password} );
210             if ($c->req->{user}) {
211                 $c->forward('/restricted_area');
212             }
213         }
214     }
215
216 This action should not go in your MyApp class...if it does, it will
217 conflict with the built-in method of the same name.  Instead, put it
218 in a Controller class.
219
220 $c->req->params->{username} and $c->req->params->{password} are html 
221 form parameters from a login form. If login succeeds, then 
222 $c->req->{user} contains the username of the authenticated user.
223
224 If you want to remember the user's login status in between further 
225 requests, then just use the C<$c-E<gt>session_login> method. Catalyst will 
226 create a session id and session cookie and automatically append session 
227 id to all urls. So all you have to do is just check $c->req->{user} 
228 where needed.
229
230 To log out a user, just call $c->session_logout.
231
232 Now let's take a look at the second variant:
233 2. user:password login/auth with roles
234
235 To use roles you need to add the following parameters to  MyApp->config in the 'authentication' section:
236
237     role_class      => 'MyApp::M::MyApp::Roles',
238     user_role_class => 'MyApp::M::MyApp::UserRoles',
239     user_role_user_field => 'user_id',
240     user_role_role_field => 'role_id',
241
242 Corresponding tables in PostgreSQL could look like this:
243
244  CREATE TABLE roles (
245    role_id  serial,
246    name     varchar(100),
247    primary key(role_id)
248  );
249
250  CREATE TABLE user_roles (
251    user_role_id  serial,
252    user_id       int,
253    role_id       int,
254    primary key(user_role_id),
255    foreign key(user_id) references users(user_id),
256    foreign key(role_id) references roles(role_id)
257  );
258
259 The 'roles' table is a list of role names and the 'user_role' table is 
260 used for the user -> role lookup.
261
262 Now if a logged-in user wants to see a location which is allowed only 
263 for people with an 'admin' role, in your controller you can check it 
264 with:
265
266     sub add : Local {
267         my ($self, $c) = @_;
268         if ($c->roles(qw/admin/)) {
269             $c->res->output("Your account has the role 'admin.'");
270         } else {
271             $c->res->output("You're not allowed to be here.");
272         }
273     }
274
275 One thing you might need is to forward non-authenticated users to a login 
276 form if they try to access restricted areas. If you want to do this 
277 controller-wide (if you have one controller for your admin section) then it's 
278 best to add a user check to a 'begin' action:
279
280     sub begin : Private {
281         my ($self, $c) = @_;
282         unless ($c->req->{user}) {
283             $c->req->action(undef);  ## notice this!!
284             $c->forward('/user/login');
285         }
286     }
287
288 Pay attention to $c->req->action(undef). This is needed because of the
289 way $c->forward works - C<forward> to C<login> gets called, but after
290 that Catalyst will still execute the action defined in the URI (e.g. if
291 you tried to go to C</add>, then first 'begin' will forward to 'login',
292 but after that 'add' will nonetheless be executed). So
293 $c->req->action(undef) undefines any actions that were to be called and
294 forwards the user where we want him/her to be.
295
296 And this is all you need to do. 
297
298 =head2 Pass-through login (and other actions)
299
300 An easy way of having assorted actions that occur during the processing
301 of a request that are orthogonal to its actual purpose - logins, silent
302 commands etc. Provide actions for these, but when they're required for
303 something else fill e.g. a form variable __login and have a sub begin
304 like so:
305
306     sub begin : Private {
307       my ($self, $c) = @_;
308       foreach my $action (qw/login docommand foo bar whatever/) {
309         if ($c->req->params->{"__${action}"}) {
310           $c->forward($action);
311         }
312       }
313     }
314
315 =head2 How to use Catalyst without mod_perl
316
317 Catalyst applications give optimum performance when run under mod_perl.
318 However sometimes mod_perl is not an option, and running under CGI is 
319 just too slow.  There's also an alternative to mod_perl that gives
320 reasonable performance named FastCGI.
321
322 =head3 Using FastCGI
323
324 To quote from L<http://www.fastcgi.com/>: "FastCGI is a language 
325 independent, scalable, extension to CGI that provides high performance 
326 without the limitations of specific server APIs."  Web server support 
327 is provided for Apache in the form of C<mod_fastcgi> and there is Perl
328 support in the C<FCGI> module.  To convert a CGI Catalyst application 
329 to FastCGI one needs to initialize an C<FCGI::Request> object and loop 
330 while the C<Accept> method returns zero.  The following code shows how 
331 it is done - and it also works as a normal, single-shot CGI script.
332
333     #!/usr/bin/perl
334     use strict;
335     use FCGI;
336     use MyApp;
337
338     my $request = FCGI::Request();
339     while ($request->Accept() >= 0) {
340         MyApp->run;
341     }
342
343 Any initialization code should be included outside the request-accept 
344 loop.
345
346 There is one little complication, which is that C<MyApp-E<gt>run> outputs a
347 complete HTTP response including the status line (e.g.: 
348 "C<HTTP/1.1 200>").
349 FastCGI just wants a set of headers, so the sample code captures the 
350 output and  drops the first line if it is an HTTP status line (note: 
351 this may change).
352
353 The Apache C<mod_fastcgi> module is provided by a number of Linux 
354 distros and is straightforward to compile for most Unix-like systems.  
355 The module provides a FastCGI Process Manager, which manages FastCGI 
356 scripts.  You configure your script as a FastCGI script with the 
357 following Apache configuration directives:
358
359     <Location /fcgi-bin>
360        AddHandler fastcgi-script fcgi
361     </Location>
362
363 or:
364
365     <Location /fcgi-bin>
366        SetHandler fastcgi-script
367        Action fastcgi-script /path/to/fcgi-bin/fcgi-script
368     </Location>
369
370 C<mod_fastcgi> provides a number of options for controlling the FastCGI
371 scripts spawned; it also allows scripts to be run to handle the
372 authentication, authorization, and access check phases.
373
374 For more information see the FastCGI documentation, the C<FCGI> module 
375 and L<http://www.fastcgi.com/>.
376  
377 =head2 Serving static content
378
379 Serving static content in Catalyst can be somewhat tricky; this recipe
380 shows one possible solution. Using this recipe will serve all static
381 content through Catalyst when developing with the built-in HTTP::Daemon
382 server, and will make it easy to use Apache to serve the content when
383 your app goes into production.
384
385 Static content is best served from a single directory within your root
386 directory. Having many different directories such as C<root/css> and
387 C<root/images> requires more code to manage, because you must separately
388 identify each static directory--if you decide to add a C<root/js>
389 directory, you'll need to change your code to account for it. In
390 contrast, keeping all static directories as subdirectories of a main
391 C<root/static> directory makes things much easier to manager. Here's an
392 example of a typical root directory structure:
393
394     root/
395     root/content.tt
396     root/controller/stuff.tt
397     root/header.tt
398     root/static/
399     root/static/css/main.css
400     root/static/images/logo.jpg
401     root/static/js/code.js
402
403
404 All static content lives under C<root/static> with everything else being
405 Template Toolkit files. Now you can identify the static content by
406 matching C<static> from within Catalyst.
407
408 =head3 Serving with HTTP::Daemon (myapp_server.pl)
409
410 To serve these files under the standalone server, we first must load the
411 Static plugin. Install L<Catalyst::Plugin::Static> if it's not already
412 installed.
413
414 In your main application class (MyApp.pm), load the plugin:
415
416     use Catalyst qw/-Debug FormValidator Static OtherPlugin/;
417
418 You will also need to make sure your end method does I<not> forward
419 static content to the view, perhaps like this:
420
421     sub end : Private {
422         my ( $self, $c ) = @_;
423
424         $c->forward( 'MyApp::V::TT' ) 
425           unless ( $c->res->body || !$c->stash->{template} );
426     }
427
428 This code will only forward to the view if a template has been
429 previously defined by a controller and if there is not already data in
430 C<$c-E<gt>res-E<gt>body>.
431
432 Next, create a controller to handle requests for the /static path. Use
433 the Helper to save time. This command will create a stub controller as
434 C<lib/MyApp/C/Static.pm>.
435
436     $ script/myapp_create.pl controller Static
437
438 Edit the file and add the following methods:
439
440     # serve all files under /static as static files
441     sub default : Path('/static') {
442         my ( $self, $c ) = @_;
443     
444         # Optional, allow the browser to cache the content
445         $c->res->headers->header( 'Cache-Control' => 'max-age=86400' );
446
447         $c->serve_static; # from Catalyst::Plugin::Static
448     }
449
450     # also handle requests for /favicon.ico
451     sub favicon : Path('/favicon.ico') {
452         my ( $self, $c ) = @_;
453     
454         $c->serve_static;
455     }
456
457 You can also define a different icon for the browser to use instead of
458 favicon.ico by using this in your HTML header:
459
460     <link rel="icon" href="/static/myapp.ico" type="image/x-icon" />
461
462 =head3 Common problems
463
464 The Static plugin makes use of the C<shared-mime-info> package to
465 automatically determine MIME types. This package is notoriously
466 difficult to install, especially on win32 and OS X. For OS X the easiest
467 path might be to install Fink, then use C<apt-get install
468 shared-mime-info>. Restart the server, and everything should be fine.
469
470 Make sure you are using the latest version (>= 0.16) for best
471 results. If you are having errors serving CSS files, or if they get
472 served as text/plain instead of text/css, you may have an outdated
473 shared-mime-info version. You may also wish to simply use the following
474 code in your Static controller:
475
476     if ($c->req->path =~ /css$/i) {
477         $c->serve_static( "text/css" );
478     } else {
479         $c->serve_static;
480     }
481
482 =head3 Serving with Apache
483
484 When using Apache, you can completely bypass Catalyst and the Static
485 controller by intercepting requests for the C<root/static> path at the
486 server level. All that is required is to define a DocumentRoot and add a
487 separate Location block for your static content. Here is a complete
488 config for this application under mod_perl 1.x:
489
490     <Perl>
491         use lib qw(/var/www/MyApp/lib);
492     </Perl>
493     PerlModule MyApp
494     
495     <VirtualHost *>
496         ServerName myapp.example.com
497         DocumentRoot /var/www/MyApp/root
498         <Location />
499             SetHandler perl-script
500             PerlHandler MyApp
501         </Location>
502         <LocationMatch "/(static|favicon.ico)">
503             SetHandler default-handler
504         </LocationMatch>
505     </VirtualHost>
506
507 And here's a simpler example that'll get you started:
508
509     Alias /static/ "/my/static/files/"
510     <Location "/static">
511         SetHandler none
512     </Location>
513
514 =head2 Forwarding with arguments
515
516 Sometimes you want to pass along arguments when forwarding to another
517 action. As of version 5.30, arguments can be passed in the call to
518 C<forward>; in earlier versions, you can manually set the arguments in
519 the Catalyst Request object:
520
521   # version 5.30 and later:
522   $c->forward('/wherever', [qw/arg1 arg2 arg3/]);
523
524   # pre-5.30
525   $c->req->args([qw/arg1 arg2 arg3/]);
526   $c->forward('/wherever');
527
528 (See L<Catalyst::Manual::Intro#Flow_Control> for more information on
529 passing arguments via C<forward>.)
530
531 =head2 Configure your application
532
533 You configure your application with the C<config> method in your
534 application class. This can be hard-coded, or brought in from a
535 separate configuration file.
536
537 =head3 Using YAML
538
539 YAML is a method for creating flexible and readable configuration
540 files. It's a great way to keep your Catalyst application configuration
541 in one easy-to-understand location.
542
543 In your application class (e.g. C<lib/MyApp.pm>):
544
545   use YAML;
546   # application setup
547   __PACKAGE__->config( YAML::LoadFile(__PACKAGE__->config->{'home'} . '/myapp.yml') );
548   __PACKAGE__->setup;
549
550 Now create C<myapp.yml> in your application home:
551
552   --- #YAML:1.0
553   # DO NOT USE TABS FOR INDENTATION OR label/value SEPARATION!!!
554   name:     MyApp
555
556   # authentication; perldoc Catalyst::Plugin::Authentication::CDBI
557   authentication:
558     user_class:           'MyApp::M::MyDB::Customer'
559     user_field:           'username'
560     password_field:       'password'
561     password_hash:        'md5'
562     role_class:           'MyApp::M::MyDB::Role'
563     user_role_class:      'MyApp::M::MyDB::PersonRole'
564     user_role_user_field: 'person'
565
566   # session; perldoc Catalyst::Plugin::Session::FastMmap
567   session:
568     expires:        '3600'
569     rewrite:        '0'
570     storage:        '/tmp/myapp.session'
571
572   # emails; perldoc Catalyst::Plugin::Email
573   # this passes options as an array :(
574   email:
575     - SMTP
576     - localhost
577
578 This is equivalent to:
579
580   # configure base package
581   __PACKAGE__->config( name => MyApp );
582   # configure authentication
583   __PACKAGE__->config->{authentication} = {
584     user_class => 'MyApp::M::MyDB::Customer',
585     ...
586   };
587   # configure sessions
588   __PACKAGE__->config->{session} = {
589     expires => 3600,
590     ...
591   };
592   # configure email sending
593   __PACKAGE__->config->{email} = [qw/SMTP localhost/];
594
595 See also L<YAML>.
596
597 =head2 Using existing CDBI (etc.) classes with Catalyst
598
599 Many people have existing Model classes that they would like to use with
600 Catalyst (or, conversely, they want to write Catalyst models that can be
601 used outside of Catalyst, e.g.  in a cron job). It's trivial to write a
602 simple component in Catalyst that slurps in an outside Model:
603
604     package MyApp::M::Catalog;
605     use base qw/Catalyst::Base Some::Other::CDBI::Module::Catalog/;
606     1;
607
608 and that's it! Now C<Some::Other::CDBI::Module::Catalog> is part of your
609 Cat app as C<MyApp::M::Catalog>.
610
611 =head2 Delivering a Custom Error Page
612
613 By default, Catalyst will display its own error page whenever it
614 encounters an error in your application. When running under C<-Debug>
615 mode, the error page is a useful screen including the error message and
616 a full Data::Dumper output of the C<$c> context object. When not in
617 C<-Debug>, users see a simple "Please come back later" screen.
618
619 To use a custom error page, use a special C<end> method to short-circuit
620 the error processing. The following is an example; you might want to
621 adjust it further depending on the needs of your application (for
622 example, any calls to C<fillform> will probably need to go into this
623 C<end> method; see L<Catalyst::Plugin::FillInForm>).
624
625     sub end : Private {
626         my ( $self, $c ) = @_;
627     
628         if ( scalar @{ $c->error } ) {
629             $c->stash->{errors}   = $c->error;
630             $c->stash->{template} = 'errors.tt';
631             $c->forward('MyApp::View::TT');
632             $c->{error} = [];
633         }
634     
635         return 1 if $c->response->status =~ /^3\d\d$/;
636         return 1 if $c->response->body;
637     
638         unless ( $c->response->content_type ) {
639             $c->response->content_type('text/html; charset=utf-8');
640         }
641     
642         $c->forward('MyApp::View::TT');
643     }
644
645 You can manually set errors in your code to trigger this page by calling
646
647     $c->error( 'You broke me!' );
648
649 =head1 AUTHOR
650
651 Sebastian Riedel, C<sri@oook.de>
652 Danijel Milicevic, C<me@danijel.de>
653 Viljo Marrandi, C<vilts@yahoo.com>  
654 Marcus Ramberg, C<mramberg@cpan.org>
655 Jesse Sheidlower, C<jester@panix.com>
656 Andy Grundman, C<andy@hybridized.org> 
657 Chisel Wright, C<pause@herlpacker.co.uk>
658
659 =head1 COPYRIGHT
660
661 This program is free software, you can redistribute it and/or modify it
662 under the same terms as Perl itself.