Updated helper
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Tutorial.pod
CommitLineData
83cea649 1=head1 NAME
2
3Catalyst::Manual::Tutorial - Getting started with Catalyst
4
5=head1 DESCRIPTION
6
7This document aims to get you up and running with Catalyst.
8
83cea649 9=head2 Installation
10
61b1e958 11The first step is to install Catalyst, and the simplest way to do this
12is to install the Catalyst bundle from CPAN:
83cea649 13
d538823f 14 $ perl -MCPAN -e 'install Task::Catalyst'
83cea649 15
61b1e958 16This will retrieve Catalyst and a number of useful extensions and
587d5860 17install them for you. This process might not be totally painless
18though, and you might want to look at CatInABox
19L<http://use.perl.org/~jk2addict/journal/28071>, especially if you are
20on a system that lacks a compiler.
83cea649 21
22
587d5860 23=head2 The very basics - Setting up the skeleton application.
83cea649 24
61b1e958 25Catalyst includes a helper script, C<catalyst.pl>, that will set up a
26skeleton application for you:
83cea649 27
387e4c50 28 $ catalyst MyApp
b248fa4a 29
387e4c50 30 created "MyApp"
31 created "MyApp/script"
587d5860 32 ... output snipped
387e4c50 33 created "MyApp/script/myapp_create.pl"
83cea649 34
587d5860 35This creates the directory structure, populated with skeleton
61b1e958 36files.
83cea649 37
587d5860 38=head2 Testing out the skeleton application
83cea649 39
40You can test out your new application by running the server script that
07e73f82 41Catalyst provides:
83cea649 42
387e4c50 43 $ cd MyApp
44 $ script/myapp_server.pl
b33ed88c 45
b460ad78 46 [...] [catalyst] [debug] Debug messages enabled
387e4c50 47 [...] [catalyst] [debug] Loaded plugins:
48 .------------------------------------------------------------------------------.
49 | Catalyst::Plugin::Static::Simple |
50 '------------------------------------------------------------------------------'
b33ed88c 51 [...] [catalyst] [debug] Loaded dispatcher "Catalyst::Dispatcher"
61b1e958 52 [...] [catalyst] [debug] Loaded engine "Catalyst::Engine::HTTP"
387e4c50 53 [...] [catalyst] [debug] Found home "/home/users/me/MyApp"
54 [...] [catalyst] [debug] Loaded Private actions:
55 .--------------------------------------+---------------------------------------.
56 | Private | Class |
57 +--------------------------------------+---------------------------------------+
58 | /default | MyApp |
59 '--------------------------------------+---------------------------------------'
b248fa4a 60
387e4c50 61 [...] [catalyst] [info] MyApp powered by Catalyst 5.5
62 You can connect to your server at http://localhost:3000
b33ed88c 63
64(Note that each line logged by Catalyst begins with a timestamp, which has
61b1e958 65been replaced here with "C<...>" so that the text fits onto the lines.)
b460ad78 66
61b1e958 67The server is now waiting for you to make requests of it. Try using
68telnet to manually make a simple GET request of the server (when
69telnet responds with "Escape character is '^]'.", type "GET / HTTP/1.0"
70and hit return twice):
83cea649 71
72 $ telnet localhost 3000
73 Trying 127.0.0.1...
74 Connected to localhost.
75 Escape character is '^]'.
76 GET / HTTP/1.0
b248fa4a 77
387e4c50 78 HTTP/1.0 200 OK
79 Date: Mon, 07 Nov 2005 14:57:39 GMT
80 Content-Length: 5525
81 Content-Type: text/html; charset=utf-8
83cea649 82 Status: 200
387e4c50 83 X-Catalyst: 5.5
83cea649 84
387e4c50 85 [...]
83cea649 86 Connection closed by foreign host.
87 $
88
387e4c50 89You can see the full welcome message by visting
90http://localhost:3000/ with your browser.
91
83cea649 92More trace messages will appear in the original terminal window:
93
387e4c50 94 [...] [catalyst] [debug] **********************************
95 [...] [catalyst] [debug] * Request 1 (0.063/s) [2148]
96 [...] [catalyst] [debug] **********************************
97 [...] [catalyst] [debug] Arguments are ""
61b1e958 98 [...] [catalyst] [debug] "GET" request for "" from localhost
387e4c50 99 [...] [catalyst] [info] Request took 0.046883s (21.330/s)
100 .------------------------------------------------------------------+-----------.
101 | Action | Time |
102 +------------------------------------------------------------------+-----------+
103 | /default | 0.000000s |
104 '------------------------------------------------------------------+-----------'
83cea649 105
106The server will continue running until you interrupt it.
107
108The application can also be tested from the command line using the generated
387e4c50 109helper script, C<script/myapp_test.pl>.
83cea649 110
8d47005f 111=head2 Getting started
83cea649 112
8d47005f 113So you picked Catalyst. Good choice. I assume you've installed it as
114well. For this tutorial you will also need the following modules:
83cea649 115
8d47005f 116L<Catalyst::Plugin::Session>
83cea649 117
8d47005f 118L<Catalyst::Plugin::Session::Store::File>
83cea649 119
8d47005f 120L<Catalyst::Plugin::Session::State::Cookie>
83cea649 121
8d47005f 122L<Catalyst::Plugin::Authentication>
83cea649 123
587d5860 124L<Catalyst::Plugin::Authentication::Store::Minimal>
125
126L<Catalyst::Plugin::Authentication::::Minimal>
127
128L<Catalyst::Plugin::Authentication::Credential::Password>
129
8d47005f 130L<Catalyst::Plugin::Authorization::Roles>
83cea649 131
8d47005f 132L<DBD::SQLite>
83cea649 133
8d47005f 134...
135
136To get started all you need to do is type:
137
138B<catalyst.pl tutorial>
139
c425bfeb 140=for commentary
141Poor choice of application name - searching for "tutorial" in the docs
142also results in discussion of the tutorial process, which is probably
143not what the reader wants.
144
145=cut
146
8d47005f 147This should create a directory called F<tutorial> and fill it with the
148default (standard) Catalyst installation. Change to this directory
149because we will be running all further commands from inside the
150F<tutorial> directory.
151
152If you now run the built-in mini-server with
153B<script/tutorial_server.pl>, it will show some standard debug messages
154in the console screen (more about those in a minute), and then inform
155you that you can now connect to the test server on port 3000. Point your
156browser at localhost:3000 to see the built-in catalyst welcome screen.
157
158The other important thing catalyst.pl did was create your root
159controller. This file is a standard perl module like all the other
160controllers that you might add to your application. It lives in the
161F<lib/> directory, and will have the same name as you supplied to the
162command above, in our case it is F<tutorial.pm>. Alongside this file is
163a directory of the same name, which is the top level namespace for the
164entire application. Thus every other module we create will be
165"tutorial::something";
166
167The root controller is used to load plugins, to configure the
168application and its plugins, and for generic private actions. We will
169explain more about those later.
170
171=head2 Debugging
172
173The simplest way to debug your Catalyst application is to run it using
b248fa4a 174the built-in mini-server as described in L<Getting started>.
8d47005f 175
176If you want to output any debugging information to the console, then
c425bfeb 177call C<< $c->log->debug() >>, passing it a string to output. For
8d47005f 178data structures, use Data::Dumper and call C<<
c425bfeb 179$c->log->debug(Dumper($structure)) >>
8d47005f 180
181=head2 Model/View/Controller
182
183The recommended method for code organization in a Catalyst application
184is known as the "Model View Controller" design pattern (also referred to
185"MVC"). The point of the MVC pattern is to divorce the dependencies of
186parts of the application from each other, and give them standard
187interfaces. Following this theory of organization should give your code
188all the benefits of modularity. The main benefits are interchangability
189of parts and reusable code.
190
191Thus you could replace your file data storage with a database or your
192oracle database with a mysql database and not have to change any of your
193controlling or view logic. Or you could later decide to output
194information from your application as RSS instead of HTML just by adding
195a new view module.
196
197=head3 Model
198
199Models deal with the storage of data. For a complex website, you may
200need multiple varied data sources, each will have it's own model class
201that provides an abstracted interface to it. In this tutorial we are
202going to be using a simple database.
203
204=head3 View
205
206Views are used to display information to the user. In a web framework,
207it is generally used to output HTML to the browser. As mentioned
208previously, views can also be used to output RSS or any other kind of
209data format. One easy way to do this with Catalyst is to use a
210templating system such as Template Toolkit. If outputting HTML is all
211you are going to do, then you will probably only need one view.
212
213=head3 Controller
214
215A controller deals with reacting to user choices, and thus controls what
216the application does. Since this is a web framework, Catalyst
217controllers are frequently used to react directly to URLs requested by
218the user. This tutorial will describe the simplest way of using
219controllers, where each path or part of a path is assigned its own
220action (or subroutine). More complex controlling mechanisms will be
221mentioned briefly, and can be read about in detail in the manual.
222
223
224=head2 Controlling
225
226Now lets write our first bit of application code. First, we would like
227our application to greet our users. We'll assume for now that our users
228will be sent to the I<users/greet> URL. To create a controller that
229serves the I<users> namespace, we run the following command in our
230F<tutorial> directory:
231
232B<script/tutorial_create.pl controller Users>
233
234This will create a Users.pm in F<lib/tutorial/Controller>. Open this
235file in an editor and take a look. You will notice there is some
236commented out code which we will ignore for now. To make something
237happen when our URL is visited, we will write a "greet" action which
238looks like this:
239
587d5860 240 sub greet : Local {
241 my ($self, $c) = @_;
8d47005f 242
c425bfeb 243 my $name = $c->req->param('name');
587d5860 244 $c->log->debug("Got name: $name\n");
8d47005f 245
587d5860 246 if ($c->req->method eq 'POST') {
247 if(!$name) {
248 $c->stash->{message} = 'Please fill in a name!';
249 }
250 else {
251 $c->stash->{message} = "Hello $name!";
252 }
61b1e958 253 }
587d5860 254 $c->stash->{template} = 'greet.tt';
255 }
8d47005f 256
257Whew! So, what does all this do? Lets take it one step at a time.
258The subroutine declaration gives the action a name. To the right of the
259name there is an attribute type that looks like this: " : Local". That
260defines which URIs will translate to this action. "Local", matches
261exactly one URI: /users/greet. The URI matched by "Local" is composed
262from the namespace minus the tutorial::controller portion, that is
263common to all controllers, and the action name itself. Because it is a
264URI, we use forward slashes instead of double colons. So, in summary,
265when a user requests http://localhost:3000/users/greet" the "greet"
587d5860 266action defined above in the Users controller will be executed.
8d47005f 267
268The second line retrieves the parameters Catalyst gives us when it calls
269our method. The first is the instance of our Users class, and the second
c425bfeb 270is commonly called the context, and named $c. From now on, whenever we
271are talking about the context object, it will be represented as $c in the code.
8d47005f 272
c425bfeb 273The context is the magical object containing any information you need from catalyst,
274or want to send to it, and is passed from action to action. You will see it used
275frequently in Catalyst applications, and a list of all its methods is available in
276the L<Catalyst> POD.
277
278On the third line we use the ->param method of the context's request object
279to retrieve one of the query parameters, just like in L<CGI>.
8d47005f 280
587d5860 281On the fourth, we make a debug output of this object on the server console,
282or the error log if running under CGI or mod_perl.
8d47005f 283
587d5860 284Next, if we have a post request, we check if the name field contains anything
285(or is "true"), if it isnt, we assign an error message to a "message" field in
286the stash. The stash is yet another method of the context object, it allows us
287to pass data on to other methods we call later, most usefully the View modules.
8d47005f 288
289If the username did contain a value, then we just set our message to
290greet the user by name.
291
292Finally, we set the special "template" variable in the stash to the name
293of the template we want our view to use to display this page.
8d47005f 294
295=head2 Viewing
296
297Ok, so reacting and checking the users data is all fine, but how do we
298actually display the page/form in the first place, and our results? As
299previously mentioned, we'll use Template Toolkit for our viewing. To
300create out TT based view, just run the following command:
301
302B<script/tutorial_create.pl view TToolkit TT>
303
304Notice that this time we not only gave it the type of module we wanted
305to create (a view), and a name, but also a third argument, "TT". This is
306a Catalyst helper module, which will make a standard template toolkit
307module for you. And that's all you need to do there.
308
309To use the view, the easiest way is to set up a standard "end" action.
310This a private action which will not be matched to a path like our
311"greet" action, but instead will be called after all other processing is
312done. Only one end action will be called, if there is one in a
313controller, it will be prefered over one in the application module, and
314so on.
b248fa4a 315
8d47005f 316Since we're writing a simple application, just add an end action like
317this to F<tutorial.pm>:
318
c425bfeb 319 sub end : Private {
320 my ($self, $c) = @_;
321 $c->forward('tutorial::View::TToolkit') unless $c->res->body();
8d47005f 322 }
323
324The first line declares the end sub, and marks it as a Private action.
325(The second and last attribute type we'll be using). The second line
326collects our standard parameters as shown in the controller's greet action.
327
328The third line directs Catalyst to pass processing on to our TToolkit
329view. The forward method, when just passed a class name, calls process
330on that classs. The standard TT view's process method renders the
331template named in the templare variable in the stash, using all the
332other variables in the stash as values to fill it in.
333
334NB: This is such a common way to end you processing that there is a
335plugin which does it for you: L<Catalyst::Plugin::DefaultEnd>.
336
337Template Toolkit also has access to the entire context object via "c",
338for example, using [% c.config.name %] in our template will output
339"tutorial", our project name.
340
341All that remains is to create a simple template called "greet.tt",
587d5860 342containing a form with a text field called "name" like below.
343
c425bfeb 344 <html><head><title> [% c.name %]</head><body>
587d5860 345 <p>[%message%]</p>
346 <form action="[%c.req.uri%]" method="post">
347 <input type="text" name="name"/>
c425bfeb 348 <input type="submit" value="Submit" name="submit"/>
587d5860 349 </form>
c425bfeb 350 </body></html>
8d47005f 351
587d5860 352In the example above, we use [%c.req.uri%], since we're posting to ourself.
353if we post to another action, we commonly use the uri_for method, like this:
354
355 [% c.uri_for('/users/greet')%]
356
357Place this file in the F<root> directory, . By default, templates are
c425bfeb 358searched for here, but we can change that, which brings us to...
8d47005f 359
360=head2 Configuring
361
362As previously mentioned, the configuration of modules, plugins and so on
363is done in the main application file. This is especially true for bits
364which need to be done before an instance of them is created, for example
365Template Toolkit.
366
367The TT View looks for its templates in the F<root> directory by default.
368Since this is also the directory that static files go in, we'd rather
369have a separate F<templates> directory. To do this, change the config
370call in F<tutorial.pm> like this:
371
372 __PACKAGE__->config( name => 'tutorial',
373 'View::TToolkit' => {
374 'INCLUDE_PATH' => __PACKAGE__->path_to('templates')
375 }
376 );
377
378And move the F<greet.tt> file from F<root> to the F<templates> directory
379(after creating it).
380
381Now we can run our application again by killing (ctrl-c) and restarting
382B<script/tutorial_server.pl>. Try connecting to
383I<localhost:3000/users/greet> with a browser and see what happens. What
384happens if you try to visit I<localhost:3000/users> ?
385
386=head2 Users and Authenticating
387
388One of the many reasons to write dynamic websites instead of just using static
389HTML, is to allow us to produce different content for different users, as well
390 as just restricting access to pages (which we could do with just Apaches
391htpasswd system).
392
393In this tutorial, we will just be using basic authentication, when writing
394a real application, you'll want to use a database or other secure store to
395contain your user data.
396
397To add authentication, all we need to do is add the
398L<Catalyst::Plugin::Authentication> module to our main application file. Then
399we need to pick a storage method (one of the
400L<Catalyst::Plugin::Authentication::Store> modules), and a method of verifying
401the users credentials (one of the
402L<Catalyst::Plugin::Authentication::Credential> modules), so just edit
403F<tutorial.pm> to look like this:
404
405 use Catalyst qw/-Debug Static::Simple Authentication
406 Authentication::Store::Minimal
407 Authentication::Credential::Password/;
408
409To configure, add some users to the config call, for example:
410
411 authentication => { 'users' =>
412 { 'fred' =>
413 { 'password' => 'fred1234',
414 }
415 }
416 }
417
418Generally, setting up configuration data for plugins is done based on the
419type of plugin. Check the documentation of the plugin for exact details. The
420details of this one are in L<Catalyst::Plugin::Authentication::Store::Minimal>.
421
422Since our user data is in the config, we can update it at runtime, and thus
423add users dynamically. (Of course, to keep them permanently we'll need to
424export our data to disk and read it back into the config on startup)
425
426To allow creation of new users we'll add a create action to our Users
427controller.
428
c425bfeb 429 sub create : Local {
587d5860 430 my ($self, $c) = @_;
c425bfeb 431 my ($username, $passwd1, $passwd2) = map { $c->req->param($_)}
8d47005f 432 ('username', 'password', 'passwordverify');
433
c425bfeb 434 if($username && $passwd1 && $passwd2) {
435 if($c->config->{authentication}{users}{$username}) {
587d5860 436 $c->stash->{message} = 'Sorry that user already exists';
437 $c->stash->{username} = $username;
8d47005f 438 }
c425bfeb 439 elsif($passwd1 eq $passwd2) {
440 $c->config->{authentication}->{users}->{$username} =
441 {password => $passwd1};
587d5860 442 $c->stash->{message} = 'User created!';
8d47005f 443 }
c425bfeb 444 else {
587d5860 445 $c->stash->{username} = $username;
c425bfeb 446 $c->stash->{message} = 'Passwords do not match!';
8d47005f 447 }
448 }
587d5860 449 $c->stash->{template} = 'usercreate.tt';
8d47005f 450 }
451
452All this is doing is checking that all the appropriate fields are filled,
453the password fields contain the same data, and then adding the user to the
454config hash. All the checks produce a message which can be displayed to
455the user via the View.
456
c425bfeb 457The usercreate.tt template looks like this:
458
459 <html><head><title>[% c.config.name %]</title></head><body>
460 <h1>Create a new user</h1>
461 <p> [% c.stash.message %] </p>
462 <form action="/users/create" method="post">
463 <p>User Name: <input type="text" name="username"/></p>
464 <p>Password: <input type="password" name="password"/></p>
465 <p>Confirm Password: <input type="password" name="passwordverify"/></p>
466 <p><input type="submit" name="submit" value="submit"></p>
467 </form>
468 </body></html>
469
470So our that users can login, we need a login action which we put in the
471Users controller:
472
473 sub login : Local {
474 my ($self, $c) = @_;
475 $c->stash->{template} = 'userlogin.tt';
476 if(!$c->login()) {
477 $c->stash->{message} = 'Please login.';
478 }
479 else {
480 $c->stash->{message} = "Welcome " . $c->user->id;
481 }
8d47005f 482 }
483
c425bfeb 484
485And the userlogin.tt template:
486
487 <html><head><title>[% c.config.name %]</title></head><body>
488<p> [% c.stash.message %] </p>
489 <form name='login' action='/users/login' method='post'>
490 <p>Username: <input type='text' name='user' /></p>
491 <p>Password: <input type='password' name='password' /></p>
492 <p><input type="submit" /></form>
493 </body></html>
494
495
8d47005f 496Verrrry simple. Since Credential::Password's "login" call extracts the
497username/password data from the query itself (assuming we use a standard
498name for our form fields), we don't have to do anything but call it.
499
500To keep the user logged in, all we need to do is add the Session modules to
501our collection, and the Auth modules will automatically use them;
502
503 use Catalyst qw/-Debug Static::Simple Authentication
504 Authentication::Store::Minimal
505 Authentication::Credential::Password
506 Session Session::Store::File Session::State::Cookie/;
507
508Magic!
509
c425bfeb 510=head2 Exercise
511
512As an exercise for the reader, do the following:
513
514Change users/greet and greet.tt so that the welcome message greets the
515user by name.
516
517Enforce user logging in by adding an auto action in tutorial.pm (see
518the L<Catalyst> documentation to find out about the auto action).
519
8d47005f 520=head2 Authorising
521
c425bfeb 522Authentication is about verifying users, Authorisation is about
523allowing them to do things. Catalyst currently has two Authorisation
524modules, Roles and ACL. The Roles module allows you to define groups
525which you can assign your users to, and then allow access to areas of
526your website to the groups. The ACL module lets you do more fine
527grained access/restriction by allowing of denying access however you
528like. (It also supports Roles as done by the roles module.) This
529example uses Catalyst::Plugin::Authorization::Roles. To use this add
530"Authorization::Roles" into the "use Catalyst" statement in
531tutorial.pm.
8d47005f 532
533Adding Roles via the Minimal store we are already using is quite simple,
534we just add a roles key to each user, defining the names of the roles
535they belong to.
536
537 authentication => { 'users' =>
538 { 'fred' =>
539 { 'password' => 'fred1234',
c425bfeb 540 'roles' => ['admin']
8d47005f 541 }
542 }
543 }
544
545We need an interface for our admins to administer the roles, i.e. assign
546the users to groups. To restrict access to certain actions, we just need
c425bfeb 547to call C<< $c->check_user_roles() >> in each action. So we can
8d47005f 548make a restricted I<localhost:3000/users/groups> page like this:
549
c425bfeb 550 sub groups : Local {
551 my ($self, $c) = @_;
587d5860 552 if($c->check_user_roles('admin')) {
8d47005f 553 # Now we can do things only an admin will see
587d5860 554 if(my $params = $c->req->params) {
555 my $users = $c->config->{authentication}{users};
556 foreach my $u (keys %$params) {
8d47005f 557 $users->{$u}{roles} = $params->{$u} if($users->{$u});
558 }
c425bfeb 559 $c->stash->{message} = 'Updated user roles!';
8d47005f 560 }
587d5860 561 else {
c425bfeb 562 $c->stash->{users} = $c->config->{authentication};
8d47005f 563 }
c425bfeb 564 $c->stash->{template} = 'usersgroups.tt';
61b1e958 565 }
587d5860 566 else {
c425bfeb 567 $c->stash->{message} = 'Admins Only!';
568 $c->stash->{template} = 'error.tt';
8d47005f 569 }
570 }
571
572What we are doing here is checking whether the logged in user (used by
573default in the check_user_roles method), is a member of the admin group.
574If it is, then we display the usergroups template, and update the users
575hash as required. Otherwise, we just show the user an error page.
576
c425bfeb 577For this simple example, the usersgroups.tt and error.tt templates could
578both look like this:
579
580 <html><head><title>[% c.config.name %]</title></head><body>
581 <p>[% c.stash.message %]</p>
582 <p>[% c.stash.users %]</p>
583 </body></html>
584
8d47005f 585And that's all there is to it.
586
c425bfeb 587=for authors
588So it's not clear what the groups action is doing - and with the
589current template, nothing happens. Running through the sample code,
590it's clear what's happening, (which is very little), but the purpose,
591and how to display data is not clear.
592
593=cut
594
595So that you can test this out properly without having to go to the
596trouble of deleting browser cookies manually, we will add a logout
597action in the Users controller:
598
599 sub logout : Local {
600 my ($self, $c) = @_;
601 $c->stash->{message} = "You have successfully logged out";
602 $c->logout;
603 }
604
605
8d47005f 606=head2 Data Storage (Modelling)
607
608Whether we want our users to be able to contribute to our website, or just
609create it from changeable data, we need to store the data somewhere. Generally
610this is done using a database, models can also be other data sources, for
611example another website, or RSS feeds.
612
613If you have or want a database, there are still choices to be made, there are
614several modules about for accessing databases via OO. The best known are
615probably L<Class::DBI> and L<DBIx::Class>. Catalyst supports making models
616using either of these.
617
618For a simple example, we will allow our users to store their favourite
619greeting in our database. Create a table called "greetings" in a database,
620that contains a "user" field and a "greeting" field. The simplest way to
621create a model of your database is to use these helper modules, for example
622with L<DBIx::Class>:
623
624B<script/tutorial_create.pl model UserData DBIC dbi:SQLite:/path/to/mydb.db>
625
626This will cause the DBIx::Class Loader to inspect your database, and create a
627module in the Model::UserData namespace for each table in your database.
628
629Now we need a form for our users to enter/edit their personal greetings in,
630we'll make a I<localhost:3000/users/editgreeting> page:
631
587d5860 632 sub editgreeting : Local {
633 my ($self, $c) = @_;
634 if($c->req->params->{greeting}) {
635 if(!$c->user_exists) {
636 $c->stash->{message} = "You're not logged in!";
8d47005f 637 }
587d5860 638 else {
c425bfeb 639 my $grtable = $c->model('UserData::Greetings');
640 my $record = $grtable->find_or_create(user => $c->user->id);
641 $record->greeting($c->req->params->{greeting};
8d47005f 642 $record->update;
587d5860 643 $c->stash->{message} = 'Greeting updated';
8d47005f 644 }
645 }
587d5860 646 $c->stash->{template} = 'usersgreeting.tt';
8d47005f 647 }
83cea649 648
c425bfeb 649Using C<< $c->user_exists >> from the Authentication plugin, this checks
8d47005f 650whether the user is logged in already. If they are, if they are, and they have
651entered a new greeting, we use DBIx::Class' C<find_or_create> to fetch or
652create a new record in the greetings table for the user. Once we have the
653record, we change the value of the greeting field, and call C<update> to store
654the new value in the database.
eff5f524 655
8d47005f 656=head2 Engines (Apache and FastCGI)
83cea649 657
8d47005f 658Now that we have the basics together, we can try running our application on a
659"real" server instead of just using the test server that catalyst comes
660with. L<Catalyst::Engine> is the module used to implement various types of
661servers to run it on. The currect popular ones are Apache and FastCGI. To
662force the use of a particular engine we can use the -Engine flag to Catalyst:
b460ad78 663
8d47005f 664 use Catalyst qw/-Engine=Apache/;
b460ad78 665
8d47005f 666or
b460ad78 667
8d47005f 668 use Catalyst qw/-Engine=FastCGI/;
b460ad78 669
8d47005f 670=head3 Apache
b460ad78 671
c425bfeb 672Apache also needs to be configured: we need to tell it to load your
8d47005f 673application. You can either use Catalyst for your entire website, or
674subsections. Use the Location directive to choose a path to run your
675application under:
b460ad78 676
8d47005f 677 <Location />
678 SetHandler perl-script
679 PerlResponseHandler MyApp
680 </Location>
b460ad78 681
8d47005f 682You will need to install the perl modules of your application into one of
683perls library directories, as listed by B<perl -V>, so that Apache can find
684them. Alternatively you can use the C<PerlSwitches> directive to tell Apache
685where to look:
b460ad78 686
8d47005f 687 PerlSwitches -I/path/to/MyApp/
b460ad78 688
8d47005f 689These instructions are for using Apache2 and mod_perl 2.0. If you are using
690mod_perl 1.3 or 1.99, please refer to either L<Catalyst::Engine::Apache::MP13>
691or L<Catalyst::Engine::Apache2::MP19> for slightly different ways to do it.
b460ad78 692
8d47005f 693If you wish to ensure that Apache pre-loads your application, use the
694PerlModule directive. This means that there will be less of a delay when your
695application is accessed.
b460ad78 696
8d47005f 697 PerlModule MyApp
b460ad78 698
8d47005f 699=head3 FastCGI
b460ad78 700
c425bfeb 701These instructions apply to the use of C<mod_fastcgi> under Apache
702(either 1 or 2 series).
b460ad78 703
c425bfeb 704There are 3 ways to attach a program to a URL with C<mod_fastcgi>;
705we'll examine all of them, and explain how to avoid having the
706C<myapp_fastcgi.pl> substring in the user-visible URLs.
b460ad78 707
c425bfeb 708In all of these examples, we assume that the C<DocumentRoot> is
709C</var>, that our app is called C<MyApp> and is kept in C</usr>, that
710you want the users to access the app either from the root of the
711server-uri-space, or from C</theapp>. We also assume that the general
712FastCGI settings (C<FastCgiIpcDir>, loading the module) are already
713correct (they don't depend on Catalyst or your application layout).
83cea649 714
8d47005f 715=head4 static application
716
c425bfeb 717In this setup, you tell C<mod_fastcgi> that a particular I<file> is to
718be run as a FastCGI handler. Put this somewhere in Apache's
719configuration:
8d47005f 720
721 FastCgiServer /usr/apps/MyApp/script/myapp_fastcgi.pl
722 Alias / /usr/apps/MyApp/script/myapp_fastcgi.pl/
723
724If you want your app under C</theapp>, change the C<Alias> line to:
725
726 Alias /theapp /usr/apps/MyApp/script/myapp_fastcgi.pl
727
c425bfeb 728Note the detail of the trailing C</ >: this is a general rule af the
729C<Alias> directive, both sides must end with C</ >, or both must not;
730you can't have one with C</ > and the other without, or strange things
731happen.
8d47005f 732
733=head4 dynamic application
734
c425bfeb 735In this setup, you tell C<mod_fastcgi> that certain files are to be
736treated as FastCGI handlers, in the same way you have to tell
737C<mod_cgi>. Put this in the configuration:
8d47005f 738
739 FastCgiConfig -autoUpdate
740
741 <Directory /usr/apps/MyApp/script>
742 Options +ExecCGI
743 <Files *_fastcgi.pl>
744 SetHandles fastcgi-script
745 </Files>
746 </Directory>
83cea649 747
8d47005f 748 Alias / /usr/apps/MyApp/script/myapp_fastcgi.pl/
b460ad78 749
8d47005f 750Again, if you want your app under C</theapp>, change the C<Alias> line to:
b460ad78 751
8d47005f 752 Alias /theapp /usr/apps/MyApp/script/myapp_fastcgi.pl
b460ad78 753
8d47005f 754=head4 external server
b460ad78 755
c425bfeb 756In this setup, the application is started separately from Apache, and
757communicates via a socket with C<mod_fastcgi>. This can be useful if
758you need to have a particular environment for your application (maybe
759different between applications), or you want to run them on different
760machines, or under different users for security reasons.
b460ad78 761
c425bfeb 762If you want to use a UNIX socket (on the filesystem), put this in
763Apache's configuration:
b460ad78 764
8d47005f 765 FastCgiExternalServer /tmp/somewhere -socket /tmp/myapp-socket
766 Alias / /tmp/somewhere/
b460ad78 767
c425bfeb 768Note that C</tmp> should I<not> exist: it's just a name to connect the
769two parts.
b460ad78 770
c425bfeb 771Again, if you want your app under C</theapp>, change the C<Alias> line
772to:
b460ad78 773
8d47005f 774 Alias /theapp /tmp/somewhere
775
776Then start your Catalyst application:
777
778 $ cd /usr/apps/MyApp
779 $ ./script/myapp_fastcgi -l /tmp/myapp-socket
780
c425bfeb 781If you want to use a TCP socket, simply change the C</tmp> to a
782C<host:port> pair, both in Apache's configuration and on the command
783line of your application.
8d47005f 784
785=head2 Upgrading
786
787Upgrading your application to newer Catalyst versions is quite simple. After
788installing the new Catalyst package, just run:
789
790B<catalyst.pl -scripts>
791
c425bfeb 792One level above your application directory. This will update the
793scripts directory only, and leave the rest of your app alone, If you
794wish to make use of other parts of Catalyst that have been updated,
795leave off the B<-scripts> argument, this will cause .new files to
796appear, for each module that has either been updated, or is different
797to the original because you have changed it. To find out what these
798changes are, type:
8d47005f 799
800B<diff MyApp/lib/MyApp/View/TT.pm MyApp/lib/MyApp/View/TT.pm.new>
801
c425bfeb 802for each of the changed files. (This is a Unix command, Windows users
803will need to find some equivalent). Copy any changes you need into
804your original file, then remove the .new files. (This makes life less
805complicated when the next upgrade comes around.)
8d47005f 806
c425bfeb 807=head1 AUTHORS
8d47005f 808
809Jess Robinson, C<jrobinson@cpan.org>
810Andrew Ford, C<A.Ford@ford-mason.co.uk>
811Marcus Ramberg, C<mramberg@cpan.org>
c425bfeb 812Kieren Diment, C<kd@totaldatasolution.com>
b460ad78 813
814Please send comments, corrections and suggestions for improvements to
8d47005f 815jrobinson@cpan.org
816
817=head1 TODO
818
c425bfeb 819Finish DBIC examples with templates and tested code. Make
820/users/groups do something "useful"
8d47005f 821
822Many other things..
b460ad78 823
83cea649 824=head1 COPYRIGHT
825
61b1e958 826This program is free software, you can redistribute it and/or modify
827it under the same terms as Perl itself.