Commit | Line | Data |
fc7ec1d9 |
1 | =head1 NAME |
2 | |
3 | Catalyst::Manual::Intro - Introduction to Catalyst |
4 | |
5 | =head1 DESCRIPTION |
6 | |
129cfe74 |
7 | This is a brief overview of why and how to use Catalyst. It explains how |
8 | Catalyst works and shows how to get a simple application up and running quickly. |
fc7ec1d9 |
9 | |
10 | =head2 What is Catalyst? |
11 | |
129cfe74 |
12 | Catalyst is an elegant web application framework, extremely flexible yet |
13 | extremely simple. It's similar to Ruby on Rails, Spring (Java) and L<Maypole>, |
14 | upon which it was originally based. |
fc7ec1d9 |
15 | |
16 | =head3 MVC |
17 | |
129cfe74 |
18 | Catalyst follows the Model-View-Controller (MVC) design pattern, allowing you to |
19 | easily separate concerns, like content, presentation, and flow control, into |
20 | separate modules. This separation allows you to modify code that handles one |
21 | concern without affecting code that handles the others. Catalyst promotes the |
22 | re-use of existing Perl modules that already handle common web application |
23 | concerns well. |
fc7ec1d9 |
24 | |
129cfe74 |
25 | Here's how the M, V, and C map to those concerns, with examples of well-known |
26 | Perl modules you may want to use for each. |
fc7ec1d9 |
27 | |
28 | =over 4 |
29 | |
4a6895ce |
30 | =item * B<Model> |
fc7ec1d9 |
31 | |
32 | Access and modify content (data). L<Class::DBI>, L<Plucene>, L<Net::LDAP>... |
33 | |
4a6895ce |
34 | =item * B<View> |
fc7ec1d9 |
35 | |
129cfe74 |
36 | Present content to the user. L<Template Toolkit|Template>, L<Mason|HTML::Mason>, |
37 | L<HTML::Template>... |
fc7ec1d9 |
38 | |
4a6895ce |
39 | =item * B<Controller> |
fc7ec1d9 |
40 | |
129cfe74 |
41 | Control the whole request phase, check parameters, dispatch actions, flow |
42 | control. Catalyst! |
fc7ec1d9 |
43 | |
44 | =back |
45 | |
129cfe74 |
46 | If you're unfamiliar with MVC and design patterns, you may want to check out the |
47 | original book on the subject, I<Design Patterns>, by Gamma, Helm, Johson and |
48 | Vlissides, also known as the Gang of Four (GoF). You can also just google it. |
49 | Many, many web application frameworks are based on MVC, including all those |
50 | listed above. |
fc7ec1d9 |
51 | |
52 | =head3 Flexibility |
53 | |
129cfe74 |
54 | Catalyst is much more flexible than many other frameworks. We'll talk more about |
55 | this later, but rest assured you can use your favorite Perl modules with |
56 | Catalyst. |
fc7ec1d9 |
57 | |
58 | =over 4 |
59 | |
72d9bfc7 |
60 | =item * B<Multiple Models, Views, and Controllers> |
fc7ec1d9 |
61 | |
129cfe74 |
62 | To build a Catalyst application, you handle each type of concern inside special |
63 | modules called L</Components>. Often this code will be very simple, just calling |
64 | out to Perl modules like those listed above under L</MVC>. Catalyst handles |
65 | these components in a very flexible way. Use as many Models, Views, and |
66 | Controllers as you like, using as many different Perl modules as you like, all |
67 | in the same application. Want to manipulate multiple databases, and retrieve |
68 | some data via LDAP? No problem. Want to present data from the same Model using |
69 | L<Template Toolkit|Template> and L<PDF::Template>? Easy. |
fc7ec1d9 |
70 | |
cda8d1ac |
71 | =item * B<Reuseable Components> |
fc7ec1d9 |
72 | |
129cfe74 |
73 | Not only does Catalyst promote the re-use of already existing Perl modules, it |
74 | also allows you to re-use your Catalyst components in multiple Catalyst |
75 | applications. |
fc7ec1d9 |
76 | |
4a6895ce |
77 | =item * B<Unrestrained URL-to-Action Dispatching> |
fc7ec1d9 |
78 | |
129cfe74 |
79 | Catalyst allows you to dispatch any URLs to any application L<Actions>, even |
80 | through regular expressions! Unlike most other frameworks, it doesn't require |
81 | mod_rewrite or class and method names in URLs. |
fc7ec1d9 |
82 | |
83 | With Catalyst you register your actions and address them directly. For example: |
84 | |
e3dc9d78 |
85 | sub hello : Global { |
fc7ec1d9 |
86 | my ( $self, $context ) = @_; |
87 | $context->response->output('Hello World!'); |
5a8ed4fe |
88 | } |
fc7ec1d9 |
89 | |
90 | Now http://localhost:3000/hello prints "Hello World!". |
91 | |
4a6895ce |
92 | =item * B<Support for CGI, mod_perl, Apache::Request> |
fc7ec1d9 |
93 | |
94 | Use L<Catalyst::Engine::Apache> or L<Catalyst::Engine::CGI>. |
95 | |
96 | =back |
97 | |
98 | =head3 Simplicity |
99 | |
129cfe74 |
100 | The best part is that Catalyst implements all this flexibility in a very simple |
101 | way. |
fc7ec1d9 |
102 | |
6f4e1683 |
103 | =over 4 |
104 | |
4a6895ce |
105 | =item * B<Building Block Interface> |
fc7ec1d9 |
106 | |
129cfe74 |
107 | Components interoperate very smoothly. For example, Catalyst automatically makes |
108 | a L<Context> object available to every component. Via the context, you can |
109 | access the request object, share data between components, and control the flow |
110 | of your application. Building a Catalyst application feels a lot like snapping |
111 | together toy building blocks, and everything just works. |
fc7ec1d9 |
112 | |
4a6895ce |
113 | =item * B<Component Auto-Discovery> |
fc7ec1d9 |
114 | |
129cfe74 |
115 | No need to C<use> all of your components. Catalyst automatically finds and loads |
116 | them. |
fc7ec1d9 |
117 | |
4a6895ce |
118 | =item * B<Pre-Built Components for Popular Modules> |
fc7ec1d9 |
119 | |
129cfe74 |
120 | See L<Catalyst::Model::CDBI> for L<Class::DBI>, or L<Catalyst::View::TT> for |
121 | L<Template Toolkit|Template>. You can even get an instant web database front end |
122 | with L<Catalyst::Model::CDBI::CRUD>. |
fc7ec1d9 |
123 | |
72d9bfc7 |
124 | =item * B<Built-in Test Framework> |
fc7ec1d9 |
125 | |
129cfe74 |
126 | Catalyst comes with a built-in, lightweight http server and test framework, |
127 | making it easy to test applications from the command line. |
fc7ec1d9 |
128 | |
4a6895ce |
129 | =item * B<Helper Scripts> |
fc7ec1d9 |
130 | |
129cfe74 |
131 | Catalyst provides helper scripts to quickly generate running starter code for |
132 | components and unit tests. |
fc7ec1d9 |
133 | |
6f4e1683 |
134 | =back |
135 | |
fc7ec1d9 |
136 | =head2 Quickstart |
137 | |
129cfe74 |
138 | Here's how to install Catalyst and get a simple application up and running, |
139 | using the helper scripts described above. |
fc7ec1d9 |
140 | |
141 | =head3 Install |
142 | |
143 | $ perl -MCPAN -e 'install Bundle::Catalyst' |
144 | |
145 | =head3 Setup |
146 | |
2feb6632 |
147 | $ catalyst.pl MyApp |
b33ed88c |
148 | # output omitted |
2feb6632 |
149 | $ cd MyApp |
ac4a0ae0 |
150 | $ script/myapp_create.pl controller Library::Login |
fc7ec1d9 |
151 | |
152 | =head3 Run |
153 | |
b33ed88c |
154 | $ script/myapp_server.pl |
fc7ec1d9 |
155 | |
129cfe74 |
156 | Now visit these locations with your favorite browser or user agent to see |
157 | Catalyst in action: |
fc7ec1d9 |
158 | |
159 | =over 4 |
160 | |
161 | =item http://localhost:3000/ |
162 | |
ac4a0ae0 |
163 | =item http://localhost:3000/library/login/ |
fc7ec1d9 |
164 | |
165 | =back |
166 | |
167 | Dead easy! |
168 | |
169 | =head2 How It Works |
170 | |
129cfe74 |
171 | Let's see how Catalyst works, by taking a closer look at the components and |
172 | other parts of a Catalyst application. |
fc7ec1d9 |
173 | |
174 | =head3 Application Class |
175 | |
129cfe74 |
176 | In addition to the Model, View, and Controller components, there's a single |
177 | class that represents your application itself. This is where you configure your |
178 | application, load plugins, define application-wide actions, and extend Catalyst. |
fc7ec1d9 |
179 | |
180 | package MyApp; |
181 | |
182 | use strict; |
183 | use Catalyst qw/-Debug/; |
184 | |
185 | MyApp->config( |
186 | name => 'My Application', |
187 | root => '/home/joeuser/myapp/root', |
188 | |
b33ed88c |
189 | # You can put anything else you want in here: |
190 | my_configuration_variable => 'something', |
fc7ec1d9 |
191 | ); |
192 | |
5a8ed4fe |
193 | sub default : Private { |
fc7ec1d9 |
194 | my ( $self, $context ) = @_; |
195 | $context->response->output('Catalyst rockz!'); |
5a8ed4fe |
196 | } |
fc7ec1d9 |
197 | |
198 | 1; |
199 | |
129cfe74 |
200 | For most applications, Catalyst requires you to define only two config |
201 | parameters: |
fc7ec1d9 |
202 | |
203 | =over 4 |
204 | |
4a6895ce |
205 | =item * B<name> |
fc7ec1d9 |
206 | |
207 | Name of your application. |
208 | |
4a6895ce |
209 | =item * B<root> |
fc7ec1d9 |
210 | |
72d9bfc7 |
211 | Path to additional files such as templates, images, or other static data. |
fc7ec1d9 |
212 | |
213 | =back |
214 | |
129cfe74 |
215 | However, you can define as many parameters as you want for plugins or whatever |
216 | you need. You can access them anywhere in your application via |
217 | C<$context-E<gt>config-E<gt>{$param_name}>. |
fc7ec1d9 |
218 | |
219 | =head3 Context |
220 | |
129cfe74 |
221 | Catalyst automatically blesses a Context object into your application class and |
222 | makes it available everywhere in your application. Use the Context to directly |
223 | interact with Catalyst and glue your L<Components> together. For example, if you |
224 | need to use the Context from within a Template Toolkit template, it's already |
225 | there: |
c42f5bbf |
226 | |
227 | <h1>Welcome to [% c.config.name %]!</h1> |
fc7ec1d9 |
228 | |
129cfe74 |
229 | As illustrated earlier in our URL-to-Action dispatching example, the Context is |
230 | always the second method parameter, behind the Component object reference or |
231 | class name itself. Previously we called it C<$context> for clarity, but most |
232 | Catalyst developers just call it C<$c>: |
fc7ec1d9 |
233 | |
e3dc9d78 |
234 | sub hello : Global { |
fc7ec1d9 |
235 | my ( $self, $c ) = @_; |
236 | $c->res->output('Hello World!'); |
5a8ed4fe |
237 | } |
fc7ec1d9 |
238 | |
239 | The Context contains several important objects: |
240 | |
241 | =over 4 |
242 | |
243 | =item * L<Catalyst::Request> |
244 | |
245 | $c->request |
246 | $c->req # alias |
247 | |
129cfe74 |
248 | The request object contains all kinds of request-specific information, like |
249 | query parameters, cookies, uploads, headers, and more. |
fc7ec1d9 |
250 | |
251 | $c->req->params->{foo}; |
252 | $c->req->cookies->{sessionid}; |
253 | $c->req->headers->content_type; |
254 | $c->req->base; |
255 | |
afdca3a3 |
256 | =item * L<Catalyst::Response> |
fc7ec1d9 |
257 | |
258 | $c->response |
259 | $c->res # alias |
260 | |
129cfe74 |
261 | The response is like the request, but contains just response-specific |
262 | information. |
fc7ec1d9 |
263 | |
264 | $c->res->output('Hello World'); |
265 | $c->res->status(404); |
266 | $c->res->redirect('http://oook.de'); |
267 | |
268 | =item * L<Catalyst::Config> |
269 | |
270 | $c->config |
271 | |
272 | $c->config->root; |
273 | $c->config->name; |
274 | |
275 | =item * L<Catalyst::Log> |
276 | |
277 | $c->log |
278 | |
279 | $c->log->debug('Something happened'); |
280 | $c->log->info('Something you should know'); |
281 | |
4a6895ce |
282 | =item * B<Stash> |
fc7ec1d9 |
283 | |
284 | $c->stash |
285 | |
286 | $c->stash->{foo} = 'bar'; |
287 | |
288 | =back |
289 | |
129cfe74 |
290 | The last of these, the stash, is a universal hash for sharing data among |
291 | application components. For an example, we return to our 'hello' action: |
fc7ec1d9 |
292 | |
e3dc9d78 |
293 | sub hello : Global { |
5a8ed4fe |
294 | my ( $self, $c ) = @_; |
295 | $c->stash->{message} = 'Hello World!'; |
4c6807d2 |
296 | $c->forward('show_message'); |
5a8ed4fe |
297 | } |
fc7ec1d9 |
298 | |
4c6807d2 |
299 | sub show_message : Private { |
5a8ed4fe |
300 | my ( $self, $c ) = @_; |
301 | $c->res->output( $c->stash->{message} ); |
302 | } |
fc7ec1d9 |
303 | |
129cfe74 |
304 | Note that the stash should be used only for passing data in an individual |
305 | request cycle; it gets cleared at a new request. If you need to maintain more |
306 | persistent data, use a session. |
dd25a192 |
307 | |
fc7ec1d9 |
308 | =head3 Actions |
309 | |
129cfe74 |
310 | A Catalyst controller is defined by its actions. An action is a sub with a |
311 | special attribute. You've already seen some examples of actions in this |
312 | document. The URL (for example http://localhost.3000/foo/bar) consists of two |
313 | parts, the base (http://localhost:3000/ in this example) and the path (foo/bar). |
314 | Please note that the trailing slash after the hostname[:port] always belongs to |
315 | base and not to the action. |
cda8d1ac |
316 | |
317 | Catalyst supports several types of actions: |
fc7ec1d9 |
318 | |
319 | =over 4 |
320 | |
4a6895ce |
321 | =item * B<Literal> |
fc7ec1d9 |
322 | |
f29c48dd |
323 | sub bar : Path('foo/bar') { } |
fc7ec1d9 |
324 | |
325 | Matches only http://localhost:3000/foo/bar. |
326 | |
4a6895ce |
327 | =item * B<Regex> |
fc7ec1d9 |
328 | |
b33ed88c |
329 | sub bar : Regex('^item(\d+)/order(\d+)$') { } |
fc7ec1d9 |
330 | |
129cfe74 |
331 | Matches any URL that matches the pattern in the action key, e.g. |
332 | http://localhost:3000/item23/order42. The '' around the regexp is optional, but |
333 | perltidy likes it. :) |
b33ed88c |
334 | |
129cfe74 |
335 | Regex matches act globally, i.e. without reference to the namespace from which |
336 | it is called, so that a C<bar> method in the |
337 | C<MyApp::Controller::Catalog::Order::Process> namespace won't match any form of |
338 | C<bar>, C<Catalog>, C<Order>, or C<Process> unless you explicitly put this in |
339 | the regex. |
fc7ec1d9 |
340 | |
129cfe74 |
341 | If you use capturing parentheses to extract values within the matching URL (23, |
342 | 42 in the above example), those values are available in the $c->req->snippets |
343 | array. If you want to pass arguments at the end of your URL, you must use regex |
344 | action keys. See L</URL Argument Handling> below. |
fc7ec1d9 |
345 | |
72d9bfc7 |
346 | =item * B<Top-level> |
cda8d1ac |
347 | |
348 | package MyApp; |
349 | sub foo : Global { } |
350 | |
b33ed88c |
351 | Matches http://localhost:3000/foo. The function name is mapped directly |
352 | to the application base. |
cda8d1ac |
353 | |
4a6895ce |
354 | =item * B<Namespace-Prefixed> |
fc7ec1d9 |
355 | |
2feb6632 |
356 | package MyApp::C::My::Controller; |
e3dc9d78 |
357 | sub foo : Local { } |
fc7ec1d9 |
358 | |
cda8d1ac |
359 | Matches http://localhost:3000/my/controller/foo. |
fc7ec1d9 |
360 | |
129cfe74 |
361 | This action type indicates that the matching URL must be prefixed with a |
362 | modified form of the component's class (package) name. This modified class name |
363 | excludes the parts that have a pre-defined meaning in Catalyst ("MyApp::C" in |
364 | the above example), replaces "::" with "/", and converts the name to lower case. |
365 | See L</Components> for a full explanation of the pre-defined meaning of Catalyst |
366 | component class names. |
fc7ec1d9 |
367 | |
4a6895ce |
368 | =item * B<Private> |
fc7ec1d9 |
369 | |
5a8ed4fe |
370 | sub foo : Private { } |
fc7ec1d9 |
371 | |
129cfe74 |
372 | Matches no URL, and cannot be executed by requesting a URL that corresponds to |
373 | the action key. Private actions can be executed only inside a Catalyst |
374 | application, by calling the C<forward> method: |
fc7ec1d9 |
375 | |
5a8ed4fe |
376 | $c->forward('foo'); |
fc7ec1d9 |
377 | |
129cfe74 |
378 | See L</Flow Control> for a full explanation of C<forward>. Note that, as |
fc9c8698 |
379 | discussed there, when forwarding from another component, you must use |
380 | the absolute path to the method, so that a private C<bar> method in your |
381 | C<MyApp::Controller::Catalog::Order::Process> controller must, if called |
382 | from elsewhere, be reached with |
383 | C<$c-E<gt>forward('/catalog/order/process/bar')>. |
fc7ec1d9 |
384 | |
385 | =back |
386 | |
b33ed88c |
387 | B<Note:> After seeing these examples, you probably wonder what the point |
388 | is of defining names for regex and path actions. Actually, every public |
389 | action is also a private one, so you have one unified way of addressing |
390 | components in your C<forward>s. |
cda8d1ac |
391 | |
72d9bfc7 |
392 | =head4 Built-in Private Actions |
fc7ec1d9 |
393 | |
fc9c8698 |
394 | In response to specific application states, Catalyst will automatically |
395 | call these built-in private actions in your application class: |
fc7ec1d9 |
396 | |
397 | =over 4 |
398 | |
cda8d1ac |
399 | =item * B<default : Private> |
fc7ec1d9 |
400 | |
fc9c8698 |
401 | Called when no other action matches. Could be used, for example, for |
402 | displaying a generic frontpage for the main app, or an error page for |
403 | individual controllers. |
fc7ec1d9 |
404 | |
cda8d1ac |
405 | =item * B<begin : Private> |
fc7ec1d9 |
406 | |
fc9c8698 |
407 | Called at the beginning of a request, before any matching actions are |
408 | called. |
fc7ec1d9 |
409 | |
cda8d1ac |
410 | =item * B<end : Private> |
4a6895ce |
411 | |
fc7ec1d9 |
412 | Called at the end of a request, after all matching actions are called. |
413 | |
fc9c8698 |
414 | =back |
415 | |
72d9bfc7 |
416 | =head4 B<Built-in actions in controllers/autochaining> |
fc7ec1d9 |
417 | |
cda8d1ac |
418 | Package MyApp::C::Foo; |
419 | sub begin : Private { } |
5a8ed4fe |
420 | sub default : Private { } |
fc7ec1d9 |
421 | |
fc9c8698 |
422 | You can define built-in private actions within your controllers as |
423 | well. The actions will override the ones in less-specific controllers, |
424 | or your application class. In other words, for each of the three |
425 | built-in private actions, only one will be run in any request |
426 | cycle. Thus, if C<MyApp::C::Catalog::begin> exists, it will be run in |
427 | place of C<MyApp::begin> if you're in the C<catalog> namespace, and |
428 | C<MyApp::C::Catalog::Order::begin> would override this in turn. |
429 | |
430 | In addition to the normal built-ins, you have a special action for |
431 | making chains, C<auto>. Such C<auto> actions will be run after any |
432 | C<begin>, but before your action is processed. Unlike the other |
433 | built-ins, C<auto> actions I<do not> override each other; they will |
434 | be called in turn, starting with the application class and going |
435 | through to the I<most> specific class. I<This is the reverse of the |
436 | order in which the normal built-ins override each other>. |
437 | |
438 | Here are some examples of the order in which the various built-ins |
439 | would be called: |
cda8d1ac |
440 | |
441 | =over 4 |
442 | |
fc9c8698 |
443 | =item for a request for C</foo/foo> |
cda8d1ac |
444 | |
445 | MyApp::begin |
80ef2e6d |
446 | MyApp::auto |
fc9c8698 |
447 | MyApp::C::Foo::default # in the absence of MyApp::C::Foo::Foo |
cda8d1ac |
448 | MyApp::end |
449 | |
fc9c8698 |
450 | =item for a request for C</foo/bar/foo> |
cda8d1ac |
451 | |
cda8d1ac |
452 | MyApp::C::Foo::Bar::begin |
80ef2e6d |
453 | MyApp::auto |
454 | MyApp::C::Foo::auto |
fc9c8698 |
455 | MyApp::C::Foo::Bar::auto |
456 | MyApp::C::Foo::Bar::default # for MyApp::C::Foo::Bar::foo |
cda8d1ac |
457 | MyApp::C::Foo::Bar::end |
80ef2e6d |
458 | |
459 | =back |
460 | |
fc9c8698 |
461 | The C<auto> action is also distinguished by the fact that you can break |
462 | out of the processing chain by returning 0. If an C<auto> action returns |
463 | 0, any remaining actions will be skipped, except for C<end>. So, for the |
464 | request above, if the first auto returns false, the chain would look |
465 | like this: |
80ef2e6d |
466 | |
467 | =over 4 |
468 | |
fc9c8698 |
469 | =item for a request for C</foo/bar/foo> where first C<auto> returns |
470 | false |
80ef2e6d |
471 | |
472 | MyApp::C::Foo::Bar::begin |
473 | MyApp::auto |
474 | MyApp::C::Foo::Bar::end |
cda8d1ac |
475 | |
476 | =back |
4a6895ce |
477 | |
fc9c8698 |
478 | An example of why one might use this is an authentication action: you |
479 | could set up a C<auto> action to handle authentication in your |
480 | application class (which will always be called first), and if |
481 | authentication fails, returning 0 would skip any remaining methods |
482 | for that URL. |
03805733 |
483 | |
fc9c8698 |
484 | B<Note:> Looking at it another way, C<auto> actions have to return a |
485 | true value to continue processing! You can also C<die> in the autochain |
486 | action; in that case, the request will go straight to the finalize |
487 | stage, without processing further actions. |
03805733 |
488 | |
fc9c8698 |
489 | =head4 B<URL Path Handling> |
4a6895ce |
490 | |
fc9c8698 |
491 | You can pass variable arguments as part of the URL path. In this case, |
492 | you must use regex action keys with '^' and '$' anchors, and the |
493 | arguments must be separated with forward slashes (/) in the URL. For |
494 | example, suppose you want to handle C</foo/$bar/$baz>, where C<$bar> and |
495 | C<$baz> may vary: |
4a6895ce |
496 | |
cda8d1ac |
497 | sub foo : Regex('^foo$') { my ($self, $context, $bar, $baz) = @_; } |
4a6895ce |
498 | |
fc9c8698 |
499 | But what if you also defined actions for C</foo/boo> and C</foo/boo/hoo>? |
4a6895ce |
500 | |
f29c48dd |
501 | sub boo : Path('foo/boo') { .. } |
502 | sub hoo : Path('foo/boo/hoo') { .. } |
4a6895ce |
503 | |
504 | Catalyst matches actions in most specific to least specific order: |
505 | |
506 | /foo/boo/hoo |
507 | /foo/boo |
fc9c8698 |
508 | /foo # might be /foo/bar/baz but won't be /foo/boo/hoo |
4a6895ce |
509 | |
fc9c8698 |
510 | So Catalyst would never mistakenly dispatch the first two URLs to the |
511 | '^foo$' action. |
fc7ec1d9 |
512 | |
2ef2fb0f |
513 | =head4 B<Parameter Processing> |
514 | |
fc9c8698 |
515 | Parameters passed in the URL query string are handled with methods in |
516 | the L<Catalyst::Request> class. The C<param> method is functionally |
517 | equivalent to the C<param> method of C<CGI.pm> and can be used in |
518 | modules that require this. |
2ef2fb0f |
519 | |
520 | # http://localhost:3000/catalog/view/?category=hardware&page=3 |
521 | my $category = $c->req->param('category'); |
522 | my $current_page = $c->req->param('page') || 1; |
523 | |
524 | # multiple values for single parameter name |
525 | my @values = $c->req->param('scrolling_list'); |
526 | |
527 | # DFV requires a CGI.pm-like input hash |
528 | my $results = Data::FormValidator->check($c->req->params, \%dfv_profile); |
529 | |
fc7ec1d9 |
530 | =head3 Flow Control |
531 | |
d08ced28 |
532 | You control the application flow with the C<forward> method, which |
533 | accepts the key of an action to execute. This can be an action in the |
534 | same or another Catalyst controller, or a Class name, optionally |
535 | followed by a method name. After a C<forward>, the control flow will |
536 | return to the method from which the C<forward> was issued. |
537 | |
538 | A C<forward> is similar to a method call. The main differences are that |
539 | it wraps the call in an C<eval> to allow exception handling; it |
540 | automatically passes along the context object (C<$c> or C<$context>); |
541 | and it allows profiling of each call (displayed in the log with |
542 | debugging enabled). |
fc7ec1d9 |
543 | |
e3dc9d78 |
544 | sub hello : Global { |
5a8ed4fe |
545 | my ( $self, $c ) = @_; |
546 | $c->stash->{message} = 'Hello World!'; |
d08ced28 |
547 | $c->forward('check_message'); # $c is automatically included |
5a8ed4fe |
548 | } |
fc7ec1d9 |
549 | |
4c6807d2 |
550 | sub check_message : Private { |
5a8ed4fe |
551 | my ( $self, $c ) = @_; |
552 | return unless $c->stash->{message}; |
4c6807d2 |
553 | $c->forward('show_message'); |
5a8ed4fe |
554 | } |
fc7ec1d9 |
555 | |
4c6807d2 |
556 | sub show_message : Private { |
5a8ed4fe |
557 | my ( $self, $c ) = @_; |
558 | $c->res->output( $c->stash->{message} ); |
559 | } |
3323f920 |
560 | |
d08ced28 |
561 | A C<forward> does not create a new request, so your request |
562 | object (C<$c-E<gt>req>) will remain unchanged. This is a |
563 | key difference between using C<forward> and issuing a |
564 | redirect. |
3323f920 |
565 | |
d08ced28 |
566 | You can pass new arguments to a C<forward> by adding them |
567 | in an anonymous array. In this case C<$c-E<gt>req-E<gt>args> |
568 | will be changed for the duration of the C<forward> only; upon |
569 | return, the original value of C<$c-E<gt>req-E<gt>args> will |
570 | be reset. |
3323f920 |
571 | |
572 | sub hello : Global { |
573 | my ( $self, $c ) = @_; |
574 | $c->stash->{message} = 'Hello World!'; |
d08ced28 |
575 | $c->forward('check_message',[qw/test1/]); |
576 | # now $c->req->args is back to what it was before |
3323f920 |
577 | } |
578 | |
d08ced28 |
579 | sub check_message : Private { |
580 | my ( $self, $c ) = @_; |
581 | my $first_argument = $c->req->args[0]; # now = 'test1' |
582 | # do something... |
583 | } |
cda8d1ac |
584 | |
d08ced28 |
585 | As you can see from these examples, you can just use the method name as |
586 | long as you are referring to methods in the same controller. If you want |
587 | to forward to a method in another controller, or the main application, |
588 | you will have to refer to the method by absolute path. |
cda8d1ac |
589 | |
590 | $c->forward('/my/controller/action'); |
d08ced28 |
591 | $c->forward('/default'); # calls default in main application |
fc7ec1d9 |
592 | |
d08ced28 |
593 | Here are some examples of how to forward to classes and methods. |
fc7ec1d9 |
594 | |
e3dc9d78 |
595 | sub hello : Global { |
5a8ed4fe |
596 | my ( $self, $c ) = @_; |
597 | $c->forward(qw/MyApp::M::Hello say_hello/); |
598 | } |
fc7ec1d9 |
599 | |
e3dc9d78 |
600 | sub bye : Global { |
5a8ed4fe |
601 | my ( $self, $c ) = @_; |
d08ced28 |
602 | $c->forward('MyApp::M::Hello'); # no method: will try 'process' |
5a8ed4fe |
603 | } |
fc7ec1d9 |
604 | |
605 | package MyApp::M::Hello; |
606 | |
607 | sub say_hello { |
608 | my ( $self, $c ) = @_; |
609 | $c->res->output('Hello World!'); |
610 | } |
611 | |
612 | sub process { |
613 | my ( $self, $c ) = @_; |
614 | $c->res->output('Goodbye World!'); |
615 | } |
616 | |
d08ced28 |
617 | Note that C<forward> returns to the calling action and continues |
618 | processing after the action finishes. Catalyst will automatically try |
619 | to call process() if you omit the method. |
fc7ec1d9 |
620 | |
621 | =head3 Components |
622 | |
129cfe74 |
623 | Catalyst has an uncommonly flexible component system. You can define as many |
624 | L<Models>, L<Views>, and L<Controllers> as you like. |
fc7ec1d9 |
625 | |
129cfe74 |
626 | All components must inherit from L<Catalyst::Base>, which provides a simple |
627 | class structure and some common class methods like C<config> and C<new> |
628 | (constructor). |
fc7ec1d9 |
629 | |
ac4a0ae0 |
630 | package MyApp::C::Catalog; |
fc7ec1d9 |
631 | |
632 | use strict; |
633 | use base 'Catalyst::Base'; |
634 | |
635 | __PACKAGE__->config( foo => 'bar' ); |
636 | |
637 | 1; |
638 | |
129cfe74 |
639 | You don't have to C<use> or otherwise register Models, Views, and Controllers. |
640 | Catalyst automatically discovers and instantiates them when you call C<setup> in |
641 | the main application. All you need to do is put them in directories named for |
642 | each Component type. Notice that you can use some very terse aliases for each |
643 | one. |
fc7ec1d9 |
644 | |
645 | =over 4 |
646 | |
4a6895ce |
647 | =item * B<MyApp/Model/> |
fc7ec1d9 |
648 | |
4a6895ce |
649 | =item * B<MyApp/M/> |
fc7ec1d9 |
650 | |
4a6895ce |
651 | =item * B<MyApp/View/> |
fc7ec1d9 |
652 | |
4a6895ce |
653 | =item * B<MyApp/V/> |
fc7ec1d9 |
654 | |
4a6895ce |
655 | =item * B<MyApp/Controller/> |
fc7ec1d9 |
656 | |
4a6895ce |
657 | =item * B<MyApp/C/> |
fc7ec1d9 |
658 | |
659 | =back |
660 | |
661 | =head4 Views |
662 | |
129cfe74 |
663 | To show how to define views, we'll use an already-existing base class for the |
664 | L<Template Toolkit|Template>, L<Catalyst::View::TT>. All we need to do is |
665 | inherit from this class: |
fc7ec1d9 |
666 | |
667 | package MyApp::V::TT; |
668 | |
669 | use strict; |
670 | use base 'Catalyst::View::TT'; |
671 | |
672 | 1; |
673 | |
b33ed88c |
674 | (You can also generate this automatically by using the helper script: |
675 | |
676 | script/myapp_create.pl view TT TT |
677 | |
678 | where the first C<TT> tells the script to create a Template Toolkit |
679 | view, and the second tells the script that its name should be C<TT>.) |
680 | |
129cfe74 |
681 | This gives us a process() method and we can now just do |
682 | $c->forward('MyApp::V::TT') to render our templates. The base class makes |
683 | process() implicit, so we don't have to say C<$c-E<gt>forward(qw/MyApp::V::TT |
684 | process/)>. |
fc7ec1d9 |
685 | |
e3dc9d78 |
686 | sub hello : Global { |
5a8ed4fe |
687 | my ( $self, $c ) = @_; |
688 | $c->stash->{template} = 'hello.tt'; |
689 | } |
fc7ec1d9 |
690 | |
5a8ed4fe |
691 | sub end : Private { |
692 | my ( $self, $c ) = @_; |
2feb6632 |
693 | $c->forward('MyApp::V::TT'); |
5a8ed4fe |
694 | } |
fc7ec1d9 |
695 | |
129cfe74 |
696 | You normally render templates at the end of a request, so it's a perfect use for |
697 | the global C<end> action. |
fc7ec1d9 |
698 | |
129cfe74 |
699 | Also, be sure to put the template under the directory specified in |
700 | C<$c-E<gt>config-E<gt>{root}>, or you'll be forced to look at our eyecandy debug |
701 | screen. ;) |
fc7ec1d9 |
702 | |
703 | =head4 Models |
704 | |
129cfe74 |
705 | To show how to define models, again we'll use an already-existing base class, |
706 | this time for L<Class::DBI>: L<Catalyst::Model::CDBI>. |
fc7ec1d9 |
707 | |
708 | But first, we need a database. |
709 | |
710 | -- myapp.sql |
711 | CREATE TABLE foo ( |
712 | id INTEGER PRIMARY KEY, |
713 | data TEXT |
714 | ); |
715 | |
716 | CREATE TABLE bar ( |
717 | id INTEGER PRIMARY KEY, |
718 | foo INTEGER REFERENCES foo, |
719 | data TEXT |
720 | ); |
721 | |
722 | INSERT INTO foo (data) VALUES ('TEST!'); |
723 | |
724 | |
725 | % sqlite /tmp/myapp.db < myapp.sql |
726 | |
727 | Now we can create a CDBI component for this database. |
728 | |
729 | package MyApp::M::CDBI; |
730 | |
731 | use strict; |
732 | use base 'Catalyst::Model::CDBI'; |
733 | |
734 | __PACKAGE__->config( |
735 | dsn => 'dbi:SQLite:/tmp/myapp.db', |
736 | relationships => 1 |
737 | ); |
738 | |
739 | 1; |
740 | |
129cfe74 |
741 | Catalyst automatically loads table layouts and relationships. Use the stash to |
742 | pass data to your templates. |
fc7ec1d9 |
743 | |
744 | package MyApp; |
745 | |
746 | use strict; |
747 | use Catalyst '-Debug'; |
748 | |
749 | __PACKAGE__->config( |
750 | name => 'My Application', |
751 | root => '/home/joeuser/myapp/root' |
752 | ); |
cda8d1ac |
753 | |
754 | __PACKAGE__->setup; |
fc7ec1d9 |
755 | |
5a8ed4fe |
756 | sub end : Private { |
757 | my ( $self, $c ) = @_; |
758 | $c->stash->{template} ||= 'index.tt'; |
759 | $c->forward('MyApp::V::TT'); |
760 | } |
fc7ec1d9 |
761 | |
e3dc9d78 |
762 | sub view : Global { |
5a8ed4fe |
763 | my ( $self, $c, $id ) = @_; |
764 | $c->stash->{item} = MyApp::M::CDBI::Foo->retrieve($id); |
765 | } |
fc7ec1d9 |
766 | |
767 | 1; |
768 | |
769 | The id is [% item.data %] |
770 | |
771 | =head4 Controllers |
772 | |
129cfe74 |
773 | Multiple controllers are a good way to separate logical domains of your |
774 | application. |
fc7ec1d9 |
775 | |
776 | package MyApp::C::Login; |
777 | |
72d9bfc7 |
778 | sign-in : Local { } |
779 | new-password : Local { } |
780 | sign-out : Local { } |
fc7ec1d9 |
781 | |
782 | package MyApp::C::Catalog; |
783 | |
e3dc9d78 |
784 | sub view : Local { } |
785 | sub list : Local { } |
fc7ec1d9 |
786 | |
787 | package MyApp::C::Cart; |
788 | |
e3dc9d78 |
789 | sub add : Local { } |
790 | sub update : Local { } |
791 | sub order : Local { } |
fc7ec1d9 |
792 | |
793 | =head3 Testing |
794 | |
129cfe74 |
795 | Catalyst has a built-in http server for testing! (Later, you can easily use a |
796 | more powerful server, e.g. Apache/mod_perl, in a production environment.) |
fc7ec1d9 |
797 | |
798 | Start your application on the command line... |
799 | |
b33ed88c |
800 | script/myapp_server.pl |
fc7ec1d9 |
801 | |
802 | ...then visit http://localhost:3000/ in a browser to view the output. |
803 | |
804 | You can also do it all from the command line: |
805 | |
b33ed88c |
806 | script/myapp_test.pl http://localhost/ |
fc7ec1d9 |
807 | |
808 | Have fun! |
809 | |
3cb1db8c |
810 | =head1 SUPPORT |
811 | |
812 | IRC: |
813 | |
814 | Join #catalyst on irc.perl.org. |
815 | |
72d9bfc7 |
816 | Mailing-lists: |
3cb1db8c |
817 | |
818 | http://lists.rawmode.org/mailman/listinfo/catalyst |
819 | http://lists.rawmode.org/mailman/listinfo/catalyst-dev |
820 | |
fc7ec1d9 |
821 | =head1 AUTHOR |
822 | |
cda8d1ac |
823 | Sebastian Riedel, C<sri@oook.de> |
824 | David Naughton, C<naughton@umn.edu> |
825 | Marcus Ramberg, C<mramberg@cpan.org> |
f531dd37 |
826 | Jesse Sheidlower, C<jester@panix.com> |
129cfe74 |
827 | Danijel Milicevic, C<me@danijel.de> |
fc7ec1d9 |
828 | |
829 | =head1 COPYRIGHT |
830 | |
831 | This program is free software, you can redistribute it and/or modify it under |
832 | the same terms as Perl itself. |