Commit | Line | Data |
fc7ec1d9 |
1 | =head1 NAME |
2 | |
3 | Catalyst::Manual::Intro - Introduction to Catalyst |
4 | |
5 | =head1 DESCRIPTION |
6 | |
670b3d78 |
7 | This is a brief introduction to Catalyst. It explains the most important |
aa2b0d97 |
8 | features of how Catalyst works and shows how to get a simple application |
9 | up and running quickly. For an introduction (without code) to Catalyst |
10 | itself, and why you should be using it, see L<Catalyst::Manual::About>. |
6c5c02ba |
11 | For a systematic step-by-step introduction to writing an application |
12 | with Catalyst, see L<Catalyst::Manual::Tutorial>. |
fc7ec1d9 |
13 | |
14 | =head2 What is Catalyst? |
15 | |
129cfe74 |
16 | Catalyst is an elegant web application framework, extremely flexible yet |
56d8daeb |
17 | extremely simple. It's similar to Ruby on Rails, Spring (Java), and |
6c5c02ba |
18 | L<Maypole>, upon which it was originally based. Its most important |
19 | design philosphy is to provide easy access to all the tools you need to |
20 | develop web applications, with few restrictions on how you need to use |
21 | these tools. Under Catalyst, it is always possible to do things in a |
22 | different way. However, this does mean that it is always possible to do |
23 | things in a different way. Other web frameworks are simpler to use and |
24 | easy to get up and running, but achieve this by locking the programmer |
25 | into a single set of tools. Catalyst's emphasis on flexibility means |
26 | that you have to think more to use it. We view this as a feature. |
fc7ec1d9 |
27 | |
28 | =head3 MVC |
29 | |
e178a66a |
30 | Catalyst follows the Model-View-Controller (MVC) design pattern, |
31 | allowing you to easily separate concerns, like content, presentation, |
32 | and flow control, into separate modules. This separation allows you to |
33 | modify code that handles one concern without affecting code that handles |
34 | the others. Catalyst promotes the re-use of existing Perl modules that |
35 | already handle common web application concerns well. |
fc7ec1d9 |
36 | |
e178a66a |
37 | Here's how the M, V, and C map to those concerns, with examples of |
38 | well-known Perl modules you may want to use for each. |
fc7ec1d9 |
39 | |
40 | =over 4 |
41 | |
4a6895ce |
42 | =item * B<Model> |
fc7ec1d9 |
43 | |
e112461a |
44 | Access and modify content (data). L<DBIx::Class>, L<Class::DBI>, |
6c5c02ba |
45 | L<Xapian>, L<Net::LDAP>... |
fc7ec1d9 |
46 | |
4a6895ce |
47 | =item * B<View> |
fc7ec1d9 |
48 | |
e178a66a |
49 | Present content to the user. L<Template Toolkit|Template>, |
50 | L<Mason|HTML::Mason>, L<HTML::Template>... |
fc7ec1d9 |
51 | |
4a6895ce |
52 | =item * B<Controller> |
fc7ec1d9 |
53 | |
129cfe74 |
54 | Control the whole request phase, check parameters, dispatch actions, flow |
56d8daeb |
55 | control. Catalyst itself! |
fc7ec1d9 |
56 | |
57 | =back |
58 | |
d4ef4999 |
59 | If you're unfamiliar with MVC and design patterns, you may want to |
60 | check out the original book on the subject, I<Design Patterns>, by |
61 | Gamma, Helm, Johnson, and Vlissides, also known as the Gang of Four |
62 | (GoF). Many, many web application frameworks are based on MVC, which |
63 | is becoming a popular design method for web applications. |
fc7ec1d9 |
64 | |
65 | =head3 Flexibility |
66 | |
e178a66a |
67 | Catalyst is much more flexible than many other frameworks. We'll talk |
68 | more about this later, but rest assured you can use your favorite Perl |
69 | modules with Catalyst. |
fc7ec1d9 |
70 | |
71 | =over 4 |
72 | |
72d9bfc7 |
73 | =item * B<Multiple Models, Views, and Controllers> |
fc7ec1d9 |
74 | |
e178a66a |
75 | To build a Catalyst application, you handle each type of concern inside |
76 | special modules called L</Components>. Often this code will be very |
77 | simple, just calling out to Perl modules like those listed above under |
78 | L</MVC>. Catalyst handles these components in a very flexible way. Use |
79 | as many Models, Views, and Controllers as you like, using as many |
80 | different Perl modules as you like, all in the same application. Want to |
81 | manipulate multiple databases, and retrieve some data via LDAP? No |
82 | problem. Want to present data from the same Model using L<Template |
83 | Toolkit|Template> and L<PDF::Template>? Easy. |
fc7ec1d9 |
84 | |
cda8d1ac |
85 | =item * B<Reuseable Components> |
fc7ec1d9 |
86 | |
e178a66a |
87 | Not only does Catalyst promote the re-use of already existing Perl |
88 | modules, it also allows you to re-use your Catalyst components in |
89 | multiple Catalyst applications. |
fc7ec1d9 |
90 | |
4a6895ce |
91 | =item * B<Unrestrained URL-to-Action Dispatching> |
fc7ec1d9 |
92 | |
cccc887d |
93 | Catalyst allows you to dispatch any URLs to any application L</Actions>, |
e178a66a |
94 | even through regular expressions! Unlike most other frameworks, it |
95 | doesn't require mod_rewrite or class and method names in URLs. |
fc7ec1d9 |
96 | |
e178a66a |
97 | With Catalyst you register your actions and address them directly. For |
98 | example: |
fc7ec1d9 |
99 | |
e3dc9d78 |
100 | sub hello : Global { |
fc7ec1d9 |
101 | my ( $self, $context ) = @_; |
66f6e959 |
102 | $context->response->body('Hello World!'); |
5a8ed4fe |
103 | } |
fc7ec1d9 |
104 | |
105 | Now http://localhost:3000/hello prints "Hello World!". |
106 | |
4a6895ce |
107 | =item * B<Support for CGI, mod_perl, Apache::Request> |
fc7ec1d9 |
108 | |
109 | Use L<Catalyst::Engine::Apache> or L<Catalyst::Engine::CGI>. |
110 | |
111 | =back |
112 | |
113 | =head3 Simplicity |
114 | |
e178a66a |
115 | The best part is that Catalyst implements all this flexibility in a very |
116 | simple way. |
fc7ec1d9 |
117 | |
6f4e1683 |
118 | =over 4 |
119 | |
4a6895ce |
120 | =item * B<Building Block Interface> |
fc7ec1d9 |
121 | |
e178a66a |
122 | Components interoperate very smoothly. For example, Catalyst |
cccc887d |
123 | automatically makes a L</Context> object available to every |
e178a66a |
124 | component. Via the context, you can access the request object, share |
125 | data between components, and control the flow of your |
126 | application. Building a Catalyst application feels a lot like snapping |
129cfe74 |
127 | together toy building blocks, and everything just works. |
fc7ec1d9 |
128 | |
4a6895ce |
129 | =item * B<Component Auto-Discovery> |
fc7ec1d9 |
130 | |
e178a66a |
131 | No need to C<use> all of your components. Catalyst automatically finds |
132 | and loads them. |
fc7ec1d9 |
133 | |
4a6895ce |
134 | =item * B<Pre-Built Components for Popular Modules> |
fc7ec1d9 |
135 | |
e112461a |
136 | See L<Catalyst::Model::DBIC::Schema> for L<DBIx::Class>, or |
137 | L<Catalyst::View::TT> for L<Template Toolkit|Template>. |
fc7ec1d9 |
138 | |
72d9bfc7 |
139 | =item * B<Built-in Test Framework> |
fc7ec1d9 |
140 | |
e178a66a |
141 | Catalyst comes with a built-in, lightweight http server and test |
142 | framework, making it easy to test applications from the command line. |
fc7ec1d9 |
143 | |
4a6895ce |
144 | =item * B<Helper Scripts> |
fc7ec1d9 |
145 | |
e178a66a |
146 | Catalyst provides helper scripts to quickly generate running starter |
147 | code for components and unit tests. See L<Catalyst::Helper>. |
fc7ec1d9 |
148 | |
6f4e1683 |
149 | =back |
150 | |
fc7ec1d9 |
151 | =head2 Quickstart |
152 | |
e178a66a |
153 | Here's how to install Catalyst and get a simple application up and |
154 | running, using the helper scripts described above. |
fc7ec1d9 |
155 | |
156 | =head3 Install |
157 | |
d538823f |
158 | $ perl -MCPAN -e 'install Task::Catalyst' |
fc7ec1d9 |
159 | |
160 | =head3 Setup |
161 | |
2feb6632 |
162 | $ catalyst.pl MyApp |
b33ed88c |
163 | # output omitted |
2feb6632 |
164 | $ cd MyApp |
ac4a0ae0 |
165 | $ script/myapp_create.pl controller Library::Login |
fc7ec1d9 |
166 | |
167 | =head3 Run |
168 | |
b33ed88c |
169 | $ script/myapp_server.pl |
fc7ec1d9 |
170 | |
129cfe74 |
171 | Now visit these locations with your favorite browser or user agent to see |
172 | Catalyst in action: |
fc7ec1d9 |
173 | |
51aec62b |
174 | (NOTE: Although we create a controller here, we don't actually use it. |
175 | Both of these URLs should take you to the welcome page.) |
176 | |
177 | |
fc7ec1d9 |
178 | =over 4 |
179 | |
180 | =item http://localhost:3000/ |
181 | |
ac4a0ae0 |
182 | =item http://localhost:3000/library/login/ |
fc7ec1d9 |
183 | |
184 | =back |
185 | |
56d8daeb |
186 | Easy! |
fc7ec1d9 |
187 | |
188 | =head2 How It Works |
189 | |
e178a66a |
190 | Let's see how Catalyst works, by taking a closer look at the components |
191 | and other parts of a Catalyst application. |
fc7ec1d9 |
192 | |
193 | =head3 Application Class |
194 | |
e178a66a |
195 | In addition to the Model, View, and Controller components, there's a |
196 | single class that represents your application itself. This is where you |
c37916b0 |
197 | configure your application, load plugins, and extend Catalyst. |
fc7ec1d9 |
198 | |
199 | package MyApp; |
200 | |
201 | use strict; |
202 | use Catalyst qw/-Debug/; |
203 | |
204 | MyApp->config( |
205 | name => 'My Application', |
fc7ec1d9 |
206 | |
b33ed88c |
207 | # You can put anything else you want in here: |
208 | my_configuration_variable => 'something', |
fc7ec1d9 |
209 | ); |
fc7ec1d9 |
210 | 1; |
211 | |
6c5c02ba |
212 | In older versions of Catalyst, the application class was where you put |
213 | global actions. However, as of version 5.66, the recommended practice is |
214 | to place such actions in a special Root controller (see #####, below), |
215 | to avoid namespace collisions. |
216 | |
fc7ec1d9 |
217 | =over 4 |
218 | |
4a6895ce |
219 | =item * B<name> |
fc7ec1d9 |
220 | |
56d8daeb |
221 | The name of your application. |
fc7ec1d9 |
222 | |
fc7ec1d9 |
223 | =back |
224 | |
e178a66a |
225 | Optionally, you can specify a B<root> parameter for templates and static |
226 | data. If omitted, Catalyst will try to auto-detect the directory's |
227 | location. You can define as many parameters as you want for plugins or |
228 | whatever you need. You can access them anywhere in your application via |
229 | C<$context-E<gt>config-E<gt>{$param_name}>. |
fc7ec1d9 |
230 | |
6c5c02ba |
231 | ###### We need a short section on configuration here. |
232 | |
fc7ec1d9 |
233 | =head3 Context |
234 | |
e178a66a |
235 | Catalyst automatically blesses a Context object into your application |
236 | class and makes it available everywhere in your application. Use the |
cccc887d |
237 | Context to directly interact with Catalyst and glue your L</Components> |
e178a66a |
238 | together. For example, if you need to use the Context from within a |
239 | Template Toolkit template, it's already there: |
c42f5bbf |
240 | |
241 | <h1>Welcome to [% c.config.name %]!</h1> |
fc7ec1d9 |
242 | |
e178a66a |
243 | As illustrated in our URL-to-Action dispatching example, the Context is |
244 | always the second method parameter, behind the Component object |
245 | reference or class name itself. Previously we called it C<$context> for |
246 | clarity, but most Catalyst developers just call it C<$c>: |
fc7ec1d9 |
247 | |
e3dc9d78 |
248 | sub hello : Global { |
fc7ec1d9 |
249 | my ( $self, $c ) = @_; |
66f6e959 |
250 | $c->res->body('Hello World!'); |
5a8ed4fe |
251 | } |
fc7ec1d9 |
252 | |
253 | The Context contains several important objects: |
254 | |
255 | =over 4 |
256 | |
257 | =item * L<Catalyst::Request> |
258 | |
259 | $c->request |
260 | $c->req # alias |
261 | |
129cfe74 |
262 | The request object contains all kinds of request-specific information, like |
263 | query parameters, cookies, uploads, headers, and more. |
fc7ec1d9 |
264 | |
265 | $c->req->params->{foo}; |
266 | $c->req->cookies->{sessionid}; |
267 | $c->req->headers->content_type; |
268 | $c->req->base; |
269 | |
afdca3a3 |
270 | =item * L<Catalyst::Response> |
fc7ec1d9 |
271 | |
272 | $c->response |
273 | $c->res # alias |
274 | |
129cfe74 |
275 | The response is like the request, but contains just response-specific |
276 | information. |
fc7ec1d9 |
277 | |
66f6e959 |
278 | $c->res->body('Hello World'); |
fc7ec1d9 |
279 | $c->res->status(404); |
280 | $c->res->redirect('http://oook.de'); |
281 | |
282 | =item * L<Catalyst::Config> |
283 | |
284 | $c->config |
fc7ec1d9 |
285 | $c->config->root; |
286 | $c->config->name; |
287 | |
288 | =item * L<Catalyst::Log> |
289 | |
290 | $c->log |
fc7ec1d9 |
291 | $c->log->debug('Something happened'); |
292 | $c->log->info('Something you should know'); |
293 | |
4a6895ce |
294 | =item * B<Stash> |
fc7ec1d9 |
295 | |
296 | $c->stash |
fc7ec1d9 |
297 | $c->stash->{foo} = 'bar'; |
d4ef4999 |
298 | $c->stash->{baz} = {baz => 'qox'}; |
299 | $c->stash->{fred} = [qw/ wilma pebbles/]; |
300 | |
301 | and so on. |
fc7ec1d9 |
302 | |
303 | =back |
304 | |
129cfe74 |
305 | The last of these, the stash, is a universal hash for sharing data among |
306 | application components. For an example, we return to our 'hello' action: |
fc7ec1d9 |
307 | |
e3dc9d78 |
308 | sub hello : Global { |
5a8ed4fe |
309 | my ( $self, $c ) = @_; |
310 | $c->stash->{message} = 'Hello World!'; |
4c6807d2 |
311 | $c->forward('show_message'); |
5a8ed4fe |
312 | } |
fc7ec1d9 |
313 | |
4c6807d2 |
314 | sub show_message : Private { |
5a8ed4fe |
315 | my ( $self, $c ) = @_; |
66f6e959 |
316 | $c->res->body( $c->stash->{message} ); |
5a8ed4fe |
317 | } |
fc7ec1d9 |
318 | |
e178a66a |
319 | Note that the stash should be used only for passing data in an |
320 | individual request cycle; it gets cleared at a new request. If you need |
321 | to maintain more persistent data, use a session. |
dd25a192 |
322 | |
fc7ec1d9 |
323 | =head3 Actions |
324 | |
56d8daeb |
325 | A Catalyst controller is defined by its actions. An action is a |
326 | subroutine with a special attribute. You've already seen some examples |
327 | of actions in this document. The URL (for example |
328 | http://localhost.3000/foo/bar) consists of two parts, the base |
329 | (http://localhost:3000/ in this example) and the path (foo/bar). Please |
330 | note that the trailing slash after the hostname[:port] always belongs to |
331 | base and not to the action. |
cda8d1ac |
332 | |
c37916b0 |
333 | =over 4 |
334 | |
335 | =item * B<Application Wide Actions> |
336 | |
337 | Actions which are called at the root level of the application |
6c5c02ba |
338 | (e.g. http://localhost:3000/ ) go in MyApp::Controller::Root, like |
c37916b0 |
339 | this: |
340 | |
341 | package MyApp::Controller::Root; |
342 | use base 'Catalyst::Controller'; |
343 | # Sets the actions in this controller to be registered with no prefix |
344 | # so they function identically to actions created in MyApp.pm |
345 | __PACKAGE__->config->{namespace} = ''; |
346 | sub default : Private { |
347 | my ( $self, $context ) = @_; |
348 | $context->response->body('Catalyst rocks!'); |
349 | } |
350 | 1; |
351 | |
c37916b0 |
352 | =back |
353 | |
c37916b0 |
354 | =head4 Action types |
355 | |
cda8d1ac |
356 | Catalyst supports several types of actions: |
fc7ec1d9 |
357 | |
358 | =over 4 |
359 | |
56d8daeb |
360 | =item * B<Literal> (B<Path> actions) |
fc7ec1d9 |
361 | |
e178a66a |
362 | package MyApp::Controller::My::Controller; |
f29c48dd |
363 | sub bar : Path('foo/bar') { } |
fc7ec1d9 |
364 | |
e178a66a |
365 | Literal C<Path> actions will act relative to their current |
366 | namespace. The above example matches only |
367 | http://localhost:3000/my/controller/foo/bar. If you start your path with |
368 | a forward slash, it will match from the root. Example: |
0cf56dbc |
369 | |
e178a66a |
370 | package MyApp::Controller::My::Controller; |
0cf56dbc |
371 | sub bar : Path('/foo/bar') { } |
372 | |
fc7ec1d9 |
373 | Matches only http://localhost:3000/foo/bar. |
374 | |
e178a66a |
375 | package MyApp::Controller::My::Controller; |
0cf56dbc |
376 | sub bar : Path { } |
377 | |
e178a66a |
378 | By leaving the C<Path> definition empty, it will match on the namespace |
379 | root. The above code matches http://localhost:3000/my/controller. |
0cf56dbc |
380 | |
4a6895ce |
381 | =item * B<Regex> |
fc7ec1d9 |
382 | |
b33ed88c |
383 | sub bar : Regex('^item(\d+)/order(\d+)$') { } |
fc7ec1d9 |
384 | |
129cfe74 |
385 | Matches any URL that matches the pattern in the action key, e.g. |
e178a66a |
386 | http://localhost:3000/item23/order42. The '' around the regexp is |
387 | optional, but perltidy likes it. :) |
b33ed88c |
388 | |
e178a66a |
389 | Regex matches act globally, i.e. without reference to the namespace from |
390 | which it is called, so that a C<bar> method in the |
391 | C<MyApp::Controller::Catalog::Order::Process> namespace won't match any |
392 | form of C<bar>, C<Catalog>, C<Order>, or C<Process> unless you |
393 | explicitly put this in the regex. To achieve the above, you should |
394 | consider using a C<LocalRegex> action. |
66f6e959 |
395 | |
396 | =item * B<LocalRegex> |
397 | |
398 | sub bar : LocalRegex('^widget(\d+)$') { } |
fc7ec1d9 |
399 | |
66f6e959 |
400 | LocalRegex actions act locally. If you were to use C<bar> in |
0cf56dbc |
401 | C<MyApp::Controller::Catalog>, the above example would match urls like |
402 | http://localhost:3000/catalog/widget23. |
403 | |
e178a66a |
404 | If you omit the "C<^>" from your regex, then it will match any depth |
405 | from the controller and not immediately off of the controller name. The |
406 | following example differs from the above code in that it will match |
0cf56dbc |
407 | http://localhost:3000/catalog/foo/widget23 as well. |
408 | |
409 | package MyApp::Controller::Catalog; |
410 | sub bar : LocalRegex('widget(\d+)$') { } |
66f6e959 |
411 | |
e178a66a |
412 | For both LocalRegex and Regex actions, if you use capturing parentheses |
413 | to extract values within the matching URL, those values are available in |
2982e768 |
414 | the C<$c-E<gt>req-E<gt>captures> array. In the above example, "widget23" |
e178a66a |
415 | would capture "23" in the above example, and |
2982e768 |
416 | C<$c-E<gt>req-E<gt>captures-E<gt>[0]> would be "23". If you want to pass |
e178a66a |
417 | arguments at the end of your URL, you must use regex action keys. See |
418 | L</URL Path Handling> below. |
fc7ec1d9 |
419 | |
5882c86e |
420 | =item * B<Chained> |
e76c67cb |
421 | |
e5c7adea |
422 | The C<Chained> attribute allows you to chain public path parts together |
423 | by their private names. A chain part's path can be specified with C<PathPart> |
424 | and can be declared to expect an arbitrary number of arguments. The endpoint |
425 | of the chain specifies how many arguments it gets through the C<Args> |
426 | attribute. C<:Args(0)> would be none at all, C<:Args> without an integer |
427 | would be unlimited. The path parts that aren't endpoints are using |
428 | C<Captures> to specify how many parameters they expect to receive. As an |
429 | example setup: |
430 | |
431 | package MyApp::Controller::Greeting; |
432 | use base qw/ Catalyst::Controller /; |
433 | |
434 | # this is the beginning of our chain |
435 | sub hello : PathPart('hello') Chained('/') Captures(1) { |
436 | my ( $self, $c, $integer ) = @_; |
437 | $c->stash->{ message } = "Hello "; |
438 | $c->stash->{ arg_sum } = $integer; |
08141496 |
439 | } |
e76c67cb |
440 | |
e5c7adea |
441 | # this is our endpoint, because it has no :Captures |
442 | sub world : PathPart('world') Chained('hello') Args(1) { |
443 | my ( $self, $c, $integer ) = @_; |
444 | $c->stash->{ message } .= "World!"; |
445 | $c->stash->{ arg_sum } += $integer; |
e76c67cb |
446 | |
e5c7adea |
447 | $c->response->body( join "<br/>\n" => |
448 | $c->stash->{ message }, $c->stash->{ arg_sum } ); |
08141496 |
449 | } |
450 | |
e5c7adea |
451 | The debug output provides a separate table for chained actions, showing |
452 | the whole chain as it would match and the actions it contains. Here's |
453 | an example of the startup output with our actions above: |
454 | |
455 | ... |
456 | [debug] Loaded Path Part actions: |
457 | .-----------------------+------------------------------. |
458 | | Path Spec | Private | |
459 | +-----------------------+------------------------------+ |
460 | | /hello/*/world/* | /greeting/hello (1) | |
461 | | | => /greeting/world | |
462 | '-----------------------+------------------------------' |
463 | ... |
464 | |
465 | As you can see, Catalyst only deals with chains as whole path and |
466 | builds one for each endpoint, which are the actions with C<:Chained> |
467 | but without C<:Captures>. |
468 | |
469 | Let's assume this application gets a request at the path |
470 | C</hello/23/world/12>, what happens then? First, Catalyst will dispatch |
471 | to the C<hello> action and pass the value C<23> as argument to it after |
472 | the context. It does so because we have previously used C<:Captures(1)> |
473 | to declare that it has one path part after itself as it's argument. We |
474 | told Catalyst that this is the beginning of the chain by specifying |
475 | C<:Chained('/')>. Also note that instead of saying C<:PathPart('hello')> |
476 | we could also just have said C<:PathPart>, as it defaults to the name of |
477 | the action. |
478 | |
479 | After C<hello> has run, Catalyst goes on to dispatch to the C<world> |
480 | action. This is the last action to be called, as Catalyst knows this |
481 | is an endpoint because we specified no C<:Captures> attribute. Nevertheless |
482 | we specify that this action expects an argument, but at this point we're |
483 | using C<:Args(1)> to do that. We could also have said C<:Args> or leave |
484 | it out alltogether, which would mean this action gets all arguments that |
485 | are there. This action's C<:Chained> attribute says C<hello> and tells |
486 | Catalyst that the C<hello> action in the current controller is it's |
487 | parent. |
488 | |
489 | With this we have built a chain consisting of two public path parts. |
490 | C<hello> captures one part of the path as it's argument, and also specifies |
491 | the path root as it's parent. So this part is C</hello/$arg>. The next part |
492 | is the endpoint C<world>, expecting one argument. It sums up to the path |
493 | part C<world/$arg>. This leads to a complete chain of |
494 | C</hello/$arg/world/$arg> which is matched against the requested paths. |
495 | |
496 | This example application would, if run and called by e.g. |
497 | C</hello/23/world/12>, set the stash value C<message> to C<Hello > and |
498 | the value C<arg_sum> to C<23>. The C<world> action would then append |
499 | C<World!> to C<message> and add C<12> to the stash's C<arg_sum> value. |
500 | For the sake of simplicity no view is shown. Instead we just put the |
501 | values of the stash into our body. So the output would look like: |
502 | |
503 | Hello World! |
504 | 35 |
505 | |
506 | And our test server would've given us this debugging output for the |
507 | request: |
508 | |
509 | ... |
510 | [debug] "GET" request for "hello/23/world/12" from "127.0.0.1" |
511 | [debug] Path is "/greeting/world" |
512 | [debug] Arguments are "12" |
513 | [info] Request took 0.164113s (6.093/s) |
514 | .------------------------------------------+-----------. |
515 | | Action | Time | |
516 | +------------------------------------------+-----------+ |
517 | | /greeting/hello | 0.000029s | |
518 | | /greeting/world | 0.000024s | |
519 | '------------------------------------------+-----------' |
520 | ... |
521 | |
522 | What would be common usecases of this dispatching technique? It gives the |
523 | possibility to split up logic that contains steps that each depend on each |
524 | other. An example would be, for example, a wiki path like |
525 | C</wiki/FooBarPage/rev/23/view>. This chain can be easily built with |
526 | these actions: |
527 | |
528 | sub wiki : PathPart('wiki') Chained('/') Captures(1) { |
529 | my ( $self, $c, $page_name ) = @_; |
530 | # load the page named $page_name and put the object |
531 | # into the stash |
08141496 |
532 | } |
533 | |
e5c7adea |
534 | sub rev : PathPart('rev') Chained('wiki') Captures(1) { |
535 | my ( $self, $c, $revision_id ) = @_; |
536 | # use the page object in the stash to get at it's |
537 | # revision with number $revision_id |
08141496 |
538 | } |
539 | |
e5c7adea |
540 | sub view : PathPart Chained('rev') Args(0) { |
541 | my ( $self, $c ) = @_; |
542 | # display the revision in our stash. An other option |
543 | # would be to forward a compatible object to the action |
544 | # that displays the default wiki pages, unless we want |
545 | # a different interface here, for example restore |
546 | # functionality. |
547 | } |
e76c67cb |
548 | |
e5c7adea |
549 | It would now be possible to add other endpoints. For example C<restore> to |
550 | restore this specific revision as current state. |
551 | |
552 | Also, you of course don't have to put all the chained actions in one |
553 | controller. The specification of the parent through C<:Chained> also takes |
554 | an absolute action path as it's argument. Just specify it with a leading |
555 | C</>. |
556 | |
557 | If you want, for example, to have actions for the public paths |
558 | C</foo/12/edit> and C</foo/12>, just specify two actions with |
559 | C<:PathPart('foo')> and C<:Chained('/')>. The handler for the former |
560 | path needs a C<:Captures(1)> attribute and a endpoint with |
561 | C<:PathPart('edit')> and C<:Chained('foo')>. For the latter path give |
562 | the action just a C<:Args(1)> to mark it as endpoint. This sums up to |
563 | this debugging output: |
564 | |
565 | ... |
566 | [debug] Loaded Path Part actions: |
567 | .-----------------------+------------------------------. |
568 | | Path Spec | Private | |
569 | +-----------------------+------------------------------+ |
570 | | /foo/* | /controller/foo_view | |
571 | | /foo/*/edit | /controller/foo_load (1) | |
572 | | | => /controller/edit | |
573 | '-----------------------+------------------------------' |
574 | ... |
575 | |
576 | Here's a more detailed specification of the attributes belonging to |
577 | C<:Chained>: |
578 | |
579 | =over 8 |
580 | |
581 | =item PathPart |
582 | |
583 | Sets the name of this part of the chain. If it is specified without |
584 | arguments, it takes the name of the action as default. So basically |
585 | C<sub foo :PathPart> and C<sub foo :PathPart('foo')> are identical. |
586 | This can also contain slashes to bind to a deeper level. An action |
587 | with C<sub bar :PathPart('foo/bar') :Chained('/')> would bind to |
588 | C</foo/bar/...>. If you don't specify C<:PathPart> it has the same |
589 | effect as using C<:PathPart>, it would default to the action name. |
590 | |
591 | =item Chained |
592 | |
593 | Has to be specified for every child in the chain. Possible values are |
594 | absolute and relative private action paths, with the relatives pointing |
595 | to the current controller, or a single slash C</> to tell Catalyst that |
596 | this is the root of a chain. The attribute C<:Chained> without aguments |
597 | also defaults to the C</> behaviour. |
598 | |
599 | Due to the fact that you can specify an absolute path to the parent |
600 | action, it doesn't matter to Catalyst where that parent is located. So, |
601 | if your design requests it, you can redispatch a chain through every |
602 | controller or namespace you want. |
603 | |
604 | Another interesting possibility gives C<:Chained('.')>, which chains |
605 | itself to an action with the path of the current controllers namespace. |
606 | For example: |
607 | |
608 | # in MyApp::Controller::Foo |
609 | sub bar : Chained Captures(1) { ... } |
610 | |
611 | # in MyApp::Controller::Foo::Bar |
612 | sub baz : Chained('.') Args(1) { ... } |
613 | |
614 | This builds up a chain like C</bar/*/baz/*>. The specification of C<.> |
615 | as argument to Chained here chains the C<baz> action to an action with |
616 | the path of the current controller namespace, namely C</foo/bar>. That |
617 | action chains directly to C</>, so the above chain comes out as end |
618 | product. |
619 | |
620 | =item Captures |
621 | |
622 | Also has to be specified for every part of the chain that is not an |
623 | endpoint. With this attribute Catalyst knows how many of the following |
624 | parts of the path (separated by C</>) this action wants to captures as |
625 | it's arguments. If it doesn't expect any, just specify C<:Captures(0)>. |
626 | The captures get passed to the action's C<@_> right after the context, |
627 | but you can also find them as array reference in |
27c0dd05 |
628 | C<$c-E<gt>request-E<gt>captures-E<gt>[$level]>. The C<$level> is the |
e5c7adea |
629 | level of the action in the chain that captured the parts of the path. |
630 | |
631 | An action that is part of a chain (read: that has a C<:Chained> attribute) |
632 | but has no C<:Captures> attribute is treated by Catalyst as a chain end. |
633 | |
634 | =item Args |
635 | |
636 | By default, endpoints receive the rest of the arguments in the path. You |
637 | can tell Catalyst through C<:Args> explicitly how many arguments your |
638 | endpoint expects, just like you can with C<:Captures>. Note that this |
639 | also influences if this chain is invoked on a request. A chain with an |
640 | endpoint specifying one argument will only match if exactly one argument |
641 | exists in the path. |
642 | |
643 | You can specify an exact number of arguments like C<:Args(3)>, including |
644 | C<0>. If you just say C<:Args> without any arguments, it is the same as |
645 | leaving it out alltogether: The chain is matched independent of the number |
646 | of path parts after the endpoint. |
647 | |
648 | Just like with C<:Captures>, the arguments get passed to the action in |
649 | C<@_> after the context object. They can also be reached through |
650 | C<$c-E<gt>request-E<gt>arguments>. |
e76c67cb |
651 | |
e5c7adea |
652 | =back |
08141496 |
653 | |
d666af81 |
654 | Note that the list of C<auto> actions called depends on the private path |
655 | of the endpoint of the chain, not on the chained actions way. The C<auto> |
656 | actions will be run before the chain dispatching begins. In every other |
657 | aspect, C<auto> actions behave as documented. |
658 | |
659 | The C<forward>ing to other actions does just what you would expect. But if |
660 | you C<detach> out of a chain, the rest of the chain will not get called |
661 | after the C<detach> returned. |
662 | |
56d8daeb |
663 | =item * B<Top-level> (B<Global>) |
cda8d1ac |
664 | |
c37916b0 |
665 | package MyApp::Controller::Foo; |
cda8d1ac |
666 | sub foo : Global { } |
667 | |
c37916b0 |
668 | Matches http://localhost:3000/foo. The function name is mapped |
669 | directly to the application base. You can provide an equivalent |
670 | function in this case by doing the following: |
671 | |
672 | package MyApp::Controller::Root |
673 | sub foo : Local { } |
cda8d1ac |
674 | |
56d8daeb |
675 | =item * B<Namespace-Prefixed> (B<Local>) |
fc7ec1d9 |
676 | |
e178a66a |
677 | package MyApp::Controller::My::Controller; |
e3dc9d78 |
678 | sub foo : Local { } |
fc7ec1d9 |
679 | |
cda8d1ac |
680 | Matches http://localhost:3000/my/controller/foo. |
fc7ec1d9 |
681 | |
129cfe74 |
682 | This action type indicates that the matching URL must be prefixed with a |
e178a66a |
683 | modified form of the component's class (package) name. This modified |
684 | class name excludes the parts that have a pre-defined meaning in |
685 | Catalyst ("MyApp::Controller" in the above example), replaces "::" with |
686 | "/", and converts the name to lower case. See L</Components> for a full |
687 | explanation of the pre-defined meaning of Catalyst component class |
688 | names. |
fc7ec1d9 |
689 | |
4a6895ce |
690 | =item * B<Private> |
fc7ec1d9 |
691 | |
5a8ed4fe |
692 | sub foo : Private { } |
fc7ec1d9 |
693 | |
e178a66a |
694 | Matches no URL, and cannot be executed by requesting a URL that |
695 | corresponds to the action key. Private actions can be executed only |
696 | inside a Catalyst application, by calling the C<forward> method: |
fc7ec1d9 |
697 | |
5a8ed4fe |
698 | $c->forward('foo'); |
fc7ec1d9 |
699 | |
129cfe74 |
700 | See L</Flow Control> for a full explanation of C<forward>. Note that, as |
fc9c8698 |
701 | discussed there, when forwarding from another component, you must use |
702 | the absolute path to the method, so that a private C<bar> method in your |
703 | C<MyApp::Controller::Catalog::Order::Process> controller must, if called |
704 | from elsewhere, be reached with |
705 | C<$c-E<gt>forward('/catalog/order/process/bar')>. |
fc7ec1d9 |
706 | |
baf5120b |
707 | =item * B<Args> |
708 | |
709 | Args is not an action type per se, but an action modifier - it adds a match |
710 | restriction to any action it's provided to, requiring only as many path parts |
711 | as are specified for the action to be valid - for example in |
712 | MyApp::Controller::Foo, |
713 | |
714 | sub bar :Local |
715 | |
716 | would match any URL starting /foo/bar/. To restrict this you can do |
717 | |
718 | sub bar :Local :Args(1) |
719 | |
720 | to only match /foo/bar/*/ |
721 | |
fc7ec1d9 |
722 | =back |
723 | |
b33ed88c |
724 | B<Note:> After seeing these examples, you probably wonder what the point |
56d8daeb |
725 | is of defining names for regex and path actions. Every public action is |
726 | also a private one, so you have one unified way of addressing components |
727 | in your C<forward>s. |
cda8d1ac |
728 | |
72d9bfc7 |
729 | =head4 Built-in Private Actions |
fc7ec1d9 |
730 | |
fc9c8698 |
731 | In response to specific application states, Catalyst will automatically |
732 | call these built-in private actions in your application class: |
fc7ec1d9 |
733 | |
734 | =over 4 |
735 | |
cda8d1ac |
736 | =item * B<default : Private> |
fc7ec1d9 |
737 | |
fc9c8698 |
738 | Called when no other action matches. Could be used, for example, for |
739 | displaying a generic frontpage for the main app, or an error page for |
740 | individual controllers. |
fc7ec1d9 |
741 | |
0cf56dbc |
742 | If C<default> isn't acting how you would expect, look at using a |
cccc887d |
743 | L</Literal> C<Path> action (with an empty path string). The difference is |
e178a66a |
744 | that C<Path> takes arguments relative from the namespace and C<default> |
745 | I<always> takes arguments relative from the root, regardless of what |
746 | controller it's in. |
0cf56dbc |
747 | |
66f6e959 |
748 | =item * B<index : Private> |
749 | |
750 | C<index> is much like C<default> except that it takes no arguments |
e178a66a |
751 | and it is weighted slightly higher in the matching process. It is |
752 | useful as a static entry point to a controller, e.g. to have a static |
61a9002d |
753 | welcome page. Note that it's also weighted higher than Path. |
66f6e959 |
754 | |
cda8d1ac |
755 | =item * B<begin : Private> |
fc7ec1d9 |
756 | |
fc9c8698 |
757 | Called at the beginning of a request, before any matching actions are |
758 | called. |
fc7ec1d9 |
759 | |
cda8d1ac |
760 | =item * B<end : Private> |
4a6895ce |
761 | |
fc7ec1d9 |
762 | Called at the end of a request, after all matching actions are called. |
763 | |
fc9c8698 |
764 | =back |
765 | |
6b10c72b |
766 | =head4 Built-in actions in controllers/autochaining |
fc7ec1d9 |
767 | |
e178a66a |
768 | Package MyApp::Controller::Foo; |
cda8d1ac |
769 | sub begin : Private { } |
5a8ed4fe |
770 | sub default : Private { } |
eff5f524 |
771 | sub auto : Private { } |
fc7ec1d9 |
772 | |
fc9c8698 |
773 | You can define built-in private actions within your controllers as |
774 | well. The actions will override the ones in less-specific controllers, |
775 | or your application class. In other words, for each of the three |
776 | built-in private actions, only one will be run in any request |
e178a66a |
777 | cycle. Thus, if C<MyApp::Controller::Catalog::begin> exists, it will be |
778 | run in place of C<MyApp::begin> if you're in the C<catalog> namespace, |
779 | and C<MyApp::Controller::Catalog::Order::begin> would override this in |
780 | turn. |
fc9c8698 |
781 | |
eff5f524 |
782 | In addition to the normal built-in actions, you have a special action |
783 | for making chains, C<auto>. Such C<auto> actions will be run after any |
fc9c8698 |
784 | C<begin>, but before your action is processed. Unlike the other |
eff5f524 |
785 | built-ins, C<auto> actions I<do not> override each other; they will be |
786 | called in turn, starting with the application class and going through to |
787 | the I<most> specific class. I<This is the reverse of the order in which |
788 | the normal built-ins override each other>. |
fc9c8698 |
789 | |
790 | Here are some examples of the order in which the various built-ins |
791 | would be called: |
cda8d1ac |
792 | |
793 | =over 4 |
794 | |
fc9c8698 |
795 | =item for a request for C</foo/foo> |
cda8d1ac |
796 | |
797 | MyApp::begin |
80ef2e6d |
798 | MyApp::auto |
e178a66a |
799 | MyApp::Controller::Foo::default # in the absence of MyApp::Controller::Foo::Foo |
cda8d1ac |
800 | MyApp::end |
801 | |
fc9c8698 |
802 | =item for a request for C</foo/bar/foo> |
cda8d1ac |
803 | |
e178a66a |
804 | MyApp::Controller::Foo::Bar::begin |
80ef2e6d |
805 | MyApp::auto |
e178a66a |
806 | MyApp::Controller::Foo::auto |
807 | MyApp::Controller::Foo::Bar::auto |
808 | MyApp::Controller::Foo::Bar::default # for MyApp::Controller::Foo::Bar::foo |
809 | MyApp::Controller::Foo::Bar::end |
80ef2e6d |
810 | |
811 | =back |
812 | |
fc9c8698 |
813 | The C<auto> action is also distinguished by the fact that you can break |
814 | out of the processing chain by returning 0. If an C<auto> action returns |
815 | 0, any remaining actions will be skipped, except for C<end>. So, for the |
816 | request above, if the first auto returns false, the chain would look |
817 | like this: |
80ef2e6d |
818 | |
819 | =over 4 |
820 | |
fc9c8698 |
821 | =item for a request for C</foo/bar/foo> where first C<auto> returns |
822 | false |
80ef2e6d |
823 | |
e178a66a |
824 | MyApp::Controller::Foo::Bar::begin |
80ef2e6d |
825 | MyApp::auto |
e178a66a |
826 | MyApp::Controller::Foo::Bar::end |
cda8d1ac |
827 | |
828 | =back |
4a6895ce |
829 | |
fc9c8698 |
830 | An example of why one might use this is an authentication action: you |
831 | could set up a C<auto> action to handle authentication in your |
832 | application class (which will always be called first), and if |
833 | authentication fails, returning 0 would skip any remaining methods |
834 | for that URL. |
03805733 |
835 | |
fc9c8698 |
836 | B<Note:> Looking at it another way, C<auto> actions have to return a |
837 | true value to continue processing! You can also C<die> in the autochain |
838 | action; in that case, the request will go straight to the finalize |
839 | stage, without processing further actions. |
03805733 |
840 | |
6b10c72b |
841 | =head4 URL Path Handling |
4a6895ce |
842 | |
70d5ae49 |
843 | You can pass variable arguments as part of the URL path, separated with |
844 | forward slashes (/). If the action is a Regex or LocalRegex, the '$' anchor |
845 | must be used. For example, suppose you want to handle C</foo/$bar/$baz>, |
846 | where C<$bar> and C<$baz> may vary: |
4a6895ce |
847 | |
cda8d1ac |
848 | sub foo : Regex('^foo$') { my ($self, $context, $bar, $baz) = @_; } |
4a6895ce |
849 | |
fc9c8698 |
850 | But what if you also defined actions for C</foo/boo> and C</foo/boo/hoo>? |
4a6895ce |
851 | |
f29c48dd |
852 | sub boo : Path('foo/boo') { .. } |
853 | sub hoo : Path('foo/boo/hoo') { .. } |
4a6895ce |
854 | |
855 | Catalyst matches actions in most specific to least specific order: |
856 | |
857 | /foo/boo/hoo |
858 | /foo/boo |
fc9c8698 |
859 | /foo # might be /foo/bar/baz but won't be /foo/boo/hoo |
4a6895ce |
860 | |
fc9c8698 |
861 | So Catalyst would never mistakenly dispatch the first two URLs to the |
862 | '^foo$' action. |
fc7ec1d9 |
863 | |
70d5ae49 |
864 | If a Regex or LocalRegex action doesn't use the '$' anchor, the action will |
865 | still match a URL containing arguments, however the arguments won't be |
866 | available via C<@_>. |
867 | |
6b10c72b |
868 | =head4 Parameter Processing |
2ef2fb0f |
869 | |
fc9c8698 |
870 | Parameters passed in the URL query string are handled with methods in |
871 | the L<Catalyst::Request> class. The C<param> method is functionally |
872 | equivalent to the C<param> method of C<CGI.pm> and can be used in |
873 | modules that require this. |
2ef2fb0f |
874 | |
875 | # http://localhost:3000/catalog/view/?category=hardware&page=3 |
876 | my $category = $c->req->param('category'); |
877 | my $current_page = $c->req->param('page') || 1; |
878 | |
879 | # multiple values for single parameter name |
880 | my @values = $c->req->param('scrolling_list'); |
881 | |
882 | # DFV requires a CGI.pm-like input hash |
883 | my $results = Data::FormValidator->check($c->req->params, \%dfv_profile); |
884 | |
fc7ec1d9 |
885 | =head3 Flow Control |
886 | |
d08ced28 |
887 | You control the application flow with the C<forward> method, which |
888 | accepts the key of an action to execute. This can be an action in the |
889 | same or another Catalyst controller, or a Class name, optionally |
890 | followed by a method name. After a C<forward>, the control flow will |
891 | return to the method from which the C<forward> was issued. |
892 | |
893 | A C<forward> is similar to a method call. The main differences are that |
894 | it wraps the call in an C<eval> to allow exception handling; it |
895 | automatically passes along the context object (C<$c> or C<$context>); |
896 | and it allows profiling of each call (displayed in the log with |
897 | debugging enabled). |
fc7ec1d9 |
898 | |
e3dc9d78 |
899 | sub hello : Global { |
5a8ed4fe |
900 | my ( $self, $c ) = @_; |
901 | $c->stash->{message} = 'Hello World!'; |
d08ced28 |
902 | $c->forward('check_message'); # $c is automatically included |
5a8ed4fe |
903 | } |
fc7ec1d9 |
904 | |
4c6807d2 |
905 | sub check_message : Private { |
5a8ed4fe |
906 | my ( $self, $c ) = @_; |
907 | return unless $c->stash->{message}; |
4c6807d2 |
908 | $c->forward('show_message'); |
5a8ed4fe |
909 | } |
fc7ec1d9 |
910 | |
4c6807d2 |
911 | sub show_message : Private { |
5a8ed4fe |
912 | my ( $self, $c ) = @_; |
66f6e959 |
913 | $c->res->body( $c->stash->{message} ); |
5a8ed4fe |
914 | } |
3323f920 |
915 | |
6c5c02ba |
916 | A C<forward> does not create a new request, so your request object |
917 | (C<$c-E<gt>req>) will remain unchanged. This is a key difference between |
918 | using C<forward> and issuing a redirect. |
3323f920 |
919 | |
d08ced28 |
920 | You can pass new arguments to a C<forward> by adding them |
921 | in an anonymous array. In this case C<$c-E<gt>req-E<gt>args> |
922 | will be changed for the duration of the C<forward> only; upon |
923 | return, the original value of C<$c-E<gt>req-E<gt>args> will |
924 | be reset. |
3323f920 |
925 | |
926 | sub hello : Global { |
927 | my ( $self, $c ) = @_; |
928 | $c->stash->{message} = 'Hello World!'; |
d08ced28 |
929 | $c->forward('check_message',[qw/test1/]); |
930 | # now $c->req->args is back to what it was before |
3323f920 |
931 | } |
932 | |
d08ced28 |
933 | sub check_message : Private { |
934 | my ( $self, $c ) = @_; |
fabf3a10 |
935 | my $first_argument = $c->req->args->[0]; # now = 'test1' |
d08ced28 |
936 | # do something... |
937 | } |
b248fa4a |
938 | |
d08ced28 |
939 | As you can see from these examples, you can just use the method name as |
940 | long as you are referring to methods in the same controller. If you want |
941 | to forward to a method in another controller, or the main application, |
942 | you will have to refer to the method by absolute path. |
cda8d1ac |
943 | |
944 | $c->forward('/my/controller/action'); |
d08ced28 |
945 | $c->forward('/default'); # calls default in main application |
fc7ec1d9 |
946 | |
d08ced28 |
947 | Here are some examples of how to forward to classes and methods. |
fc7ec1d9 |
948 | |
e3dc9d78 |
949 | sub hello : Global { |
5a8ed4fe |
950 | my ( $self, $c ) = @_; |
e178a66a |
951 | $c->forward(qw/MyApp::Model::Hello say_hello/); |
5a8ed4fe |
952 | } |
fc7ec1d9 |
953 | |
e3dc9d78 |
954 | sub bye : Global { |
5a8ed4fe |
955 | my ( $self, $c ) = @_; |
e178a66a |
956 | $c->forward('MyApp::Model::Hello'); # no method: will try 'process' |
5a8ed4fe |
957 | } |
fc7ec1d9 |
958 | |
e178a66a |
959 | package MyApp::Model::Hello; |
fc7ec1d9 |
960 | |
961 | sub say_hello { |
962 | my ( $self, $c ) = @_; |
66f6e959 |
963 | $c->res->body('Hello World!'); |
fc7ec1d9 |
964 | } |
965 | |
966 | sub process { |
967 | my ( $self, $c ) = @_; |
66f6e959 |
968 | $c->res->body('Goodbye World!'); |
fc7ec1d9 |
969 | } |
970 | |
d08ced28 |
971 | Note that C<forward> returns to the calling action and continues |
13436c14 |
972 | processing after the action finishes. If you want all further processing |
973 | in the calling action to stop, use C<detach> instead, which will execute |
974 | the C<detach>ed action and not return to the calling sub. In both cases, |
975 | Catalyst will automatically try to call process() if you omit the |
976 | method. |
fc7ec1d9 |
977 | |
978 | =head3 Components |
979 | |
56d8daeb |
980 | Catalyst has an uncommonly flexible component system. You can define as |
cccc887d |
981 | many L</Models>, L</Views>, and L</Controllers> as you like. |
fc7ec1d9 |
982 | |
56d8daeb |
983 | All components must inherit from L<Catalyst::Base>, which provides a |
984 | simple class structure and some common class methods like C<config> and |
985 | C<new> (constructor). |
fc7ec1d9 |
986 | |
e178a66a |
987 | package MyApp::Controller::Catalog; |
fc7ec1d9 |
988 | |
989 | use strict; |
990 | use base 'Catalyst::Base'; |
991 | |
992 | __PACKAGE__->config( foo => 'bar' ); |
993 | |
994 | 1; |
995 | |
6b10c72b |
996 | You don't have to C<use> or otherwise register Models, Views, and |
997 | Controllers. Catalyst automatically discovers and instantiates them |
998 | when you call C<setup> in the main application. All you need to do is |
999 | put them in directories named for each Component type. Notice that you |
6c5c02ba |
1000 | can use a terse alias for each one. |
fc7ec1d9 |
1001 | |
1002 | =over 4 |
1003 | |
4a6895ce |
1004 | =item * B<MyApp/Model/> |
fc7ec1d9 |
1005 | |
4a6895ce |
1006 | =item * B<MyApp/M/> |
fc7ec1d9 |
1007 | |
4a6895ce |
1008 | =item * B<MyApp/View/> |
fc7ec1d9 |
1009 | |
4a6895ce |
1010 | =item * B<MyApp/V/> |
fc7ec1d9 |
1011 | |
4a6895ce |
1012 | =item * B<MyApp/Controller/> |
fc7ec1d9 |
1013 | |
4a6895ce |
1014 | =item * B<MyApp/C/> |
fc7ec1d9 |
1015 | |
1016 | =back |
1017 | |
6c5c02ba |
1018 | In older versions of Catalyst, the recommended practice (and the one |
1019 | automatically created by helper scripts) was to name the directories |
1020 | C<M/>, C<V/>, and C<C/>. Though these still work, we now recommend |
1021 | the use of the full names. |
1022 | |
fc7ec1d9 |
1023 | =head4 Views |
1024 | |
129cfe74 |
1025 | To show how to define views, we'll use an already-existing base class for the |
1026 | L<Template Toolkit|Template>, L<Catalyst::View::TT>. All we need to do is |
1027 | inherit from this class: |
fc7ec1d9 |
1028 | |
e178a66a |
1029 | package MyApp::View::TT; |
fc7ec1d9 |
1030 | |
1031 | use strict; |
1032 | use base 'Catalyst::View::TT'; |
1033 | |
1034 | 1; |
1035 | |
b33ed88c |
1036 | (You can also generate this automatically by using the helper script: |
1037 | |
1038 | script/myapp_create.pl view TT TT |
1039 | |
fb9257c1 |
1040 | where the first C<TT> tells the script that the name of the view should |
1041 | be C<TT>, and the second that it should be a Template Toolkit view.) |
b33ed88c |
1042 | |
129cfe74 |
1043 | This gives us a process() method and we can now just do |
e178a66a |
1044 | $c->forward('MyApp::View::TT') to render our templates. The base class |
1045 | makes process() implicit, so we don't have to say |
1046 | C<$c-E<gt>forward(qw/MyApp::View::TT process/)>. |
fc7ec1d9 |
1047 | |
e3dc9d78 |
1048 | sub hello : Global { |
5a8ed4fe |
1049 | my ( $self, $c ) = @_; |
1050 | $c->stash->{template} = 'hello.tt'; |
1051 | } |
fc7ec1d9 |
1052 | |
5a8ed4fe |
1053 | sub end : Private { |
1054 | my ( $self, $c ) = @_; |
e178a66a |
1055 | $c->forward('MyApp::View::TT'); |
5a8ed4fe |
1056 | } |
fc7ec1d9 |
1057 | |
6b10c72b |
1058 | You normally render templates at the end of a request, so it's a perfect |
1059 | use for the global C<end> action. |
fc7ec1d9 |
1060 | |
129cfe74 |
1061 | Also, be sure to put the template under the directory specified in |
6b10c72b |
1062 | C<$c-E<gt>config-E<gt>{root}>, or you'll be forced to look at our |
1063 | eyecandy debug screen. ;) |
fc7ec1d9 |
1064 | |
1065 | =head4 Models |
1066 | |
e178a66a |
1067 | To show how to define models, again we'll use an already-existing base |
e112461a |
1068 | class, this time for L<DBIx::Class>: L<Catalyst::Model::DBIC::Schema>. |
1069 | We'll also need L<DBIx::Class::Schema::Loader>. |
fc7ec1d9 |
1070 | |
1071 | But first, we need a database. |
1072 | |
1073 | -- myapp.sql |
1074 | CREATE TABLE foo ( |
1075 | id INTEGER PRIMARY KEY, |
1076 | data TEXT |
1077 | ); |
1078 | |
1079 | CREATE TABLE bar ( |
1080 | id INTEGER PRIMARY KEY, |
1081 | foo INTEGER REFERENCES foo, |
1082 | data TEXT |
1083 | ); |
1084 | |
1085 | INSERT INTO foo (data) VALUES ('TEST!'); |
1086 | |
1087 | |
1088 | % sqlite /tmp/myapp.db < myapp.sql |
1089 | |
e112461a |
1090 | Now we can create a DBIC::SchemaLoader component for this database. |
fc7ec1d9 |
1091 | |
e112461a |
1092 | script/myapp_create.pl model DBIC DBIC::SchemaLoader 'dbi:SQLite:/tmp/myapp.db' |
fc7ec1d9 |
1093 | |
e112461a |
1094 | L<DBIx::Class::Schema::Loader> automatically loads table layouts and |
1095 | relationships. Use the stash to pass data to your templates. |
fc7ec1d9 |
1096 | |
e112461a |
1097 | We add the following to MyApp/Controller/Root.pm |
b248fa4a |
1098 | |
e112461a |
1099 | sub view : Global { |
1100 | my ( $self, $c, $id ) = @_; |
1101 | |
1102 | $c->stash->{item} = $c->model('DBIC::Foo')->find($id); |
1103 | } |
fc7ec1d9 |
1104 | |
e112461a |
1105 | 1; |
1106 | |
5a8ed4fe |
1107 | sub end : Private { |
1108 | my ( $self, $c ) = @_; |
e112461a |
1109 | |
5a8ed4fe |
1110 | $c->stash->{template} ||= 'index.tt'; |
e112461a |
1111 | $c->forward( $c->view('TT') ); |
5a8ed4fe |
1112 | } |
fc7ec1d9 |
1113 | |
e112461a |
1114 | We then create a new template file "root/index.tt" containing: |
fc7ec1d9 |
1115 | |
e112461a |
1116 | The Id's data is [% item.data %] |
fc7ec1d9 |
1117 | |
6b10c72b |
1118 | Models do not have to be part of your Catalyst application; you |
1119 | can always call an outside module that serves as your Model: |
1120 | |
1121 | # in a Controller |
1122 | sub list : Local { |
1123 | my ( $self, $c ) = @_; |
e112461a |
1124 | |
6b10c72b |
1125 | $c->stash->{template} = 'list.tt'; |
e112461a |
1126 | |
1127 | use Some::Outside::DBIC::Module; |
1128 | my @records = Some::Outside::DBIC::Module->search({ |
1129 | artist => 'sri', |
1130 | }); |
1131 | |
6b10c72b |
1132 | $c->stash->{records} = \@records; |
1133 | } |
1134 | |
1135 | But by using a Model that is part of your Catalyst application, you gain |
1136 | several things: you don't have to C<use> each component, Catalyst will |
1137 | find and load it automatically at compile-time; you can C<forward> to |
26e73131 |
1138 | the module, which can only be done to Catalyst components; and only |
6b10c72b |
1139 | Catalyst components can be fetched with |
e178a66a |
1140 | C<$c-E<gt>model('SomeModel')>. |
6b10c72b |
1141 | |
1142 | Happily, since many people have existing Model classes that they |
1143 | would like to use with Catalyst (or, conversely, they want to |
1144 | write Catalyst models that can be used outside of Catalyst, e.g. |
1145 | in a cron job), it's trivial to write a simple component in |
1146 | Catalyst that slurps in an outside Model: |
1147 | |
e112461a |
1148 | package MyApp::Model::DB; |
1149 | use base qw/Catalyst::Model::DBIC::Schema/; |
1150 | __PACKAGE__->config( |
1151 | schema_class => 'Some::DBIC::Schema', |
cccc887d |
1152 | connect_info => ['dbi:SQLite:foo.db', '', '', {AutoCommit=>1}] |
e112461a |
1153 | ); |
6b10c72b |
1154 | 1; |
1155 | |
e112461a |
1156 | and that's it! Now C<Some::DBIC::Schema> is part of your |
1157 | Cat app as C<MyApp::Model::DB>. |
6b10c72b |
1158 | |
fc7ec1d9 |
1159 | =head4 Controllers |
1160 | |
129cfe74 |
1161 | Multiple controllers are a good way to separate logical domains of your |
1162 | application. |
fc7ec1d9 |
1163 | |
e178a66a |
1164 | package MyApp::Controller::Login; |
fc7ec1d9 |
1165 | |
c02f7490 |
1166 | use base qw/Catalyst::Controller/; |
1167 | |
1168 | sub sign_in : Path("sign-in") { } |
1169 | sub new_password : Path("new-password") { } |
1170 | sub sign_out : Path("sign-out") { } |
fc7ec1d9 |
1171 | |
e178a66a |
1172 | package MyApp::Controller::Catalog; |
fc7ec1d9 |
1173 | |
c02f7490 |
1174 | use base qw/Catalyst::Controller/; |
1175 | |
e3dc9d78 |
1176 | sub view : Local { } |
1177 | sub list : Local { } |
fc7ec1d9 |
1178 | |
e178a66a |
1179 | package MyApp::Controller::Cart; |
fc7ec1d9 |
1180 | |
c02f7490 |
1181 | use base qw/Catalyst::Controller/; |
1182 | |
e3dc9d78 |
1183 | sub add : Local { } |
1184 | sub update : Local { } |
1185 | sub order : Local { } |
fc7ec1d9 |
1186 | |
c02f7490 |
1187 | Note that you can also supply attributes via the Controller's config so long |
1188 | as you have at least one attribute on a subref to be exported (:Action is |
1189 | commonly used for this) - for example the following is equivalent to the same |
1190 | controller above |
1191 | |
1192 | package MyApp::Controller::Login; |
1193 | |
1194 | use base qw/Catalyst::Controller/; |
1195 | |
1196 | __PACKAGE__->config( |
1197 | actions => { |
1198 | 'sign_in' => { Path => 'sign-in' }, |
1199 | 'new_password' => { Path => 'new-password' }, |
1200 | 'sign_out' => { Path => 'sign-out' }, |
1201 | }, |
1202 | ); |
1203 | |
1204 | sub sign_in : Action { } |
1205 | sub new_password : Action { } |
1206 | sub sign_out : Action { } |
1207 | |
24cda51b |
1208 | =head3 Models |
1209 | |
1210 | Models are providers of data. This data could come from anywhere - a search |
1211 | engine index, a database table, etc. Typically the data source does not have |
1212 | much to do with web applications or Catalyst - it could be used to write an |
1213 | offline report generator or a command line tool just the same. |
1214 | |
1215 | The common approach to writing a Catalyst-style model for your application is |
1216 | wrapping a generic model (e.g. L<DBIx::Class::Schema>, a bunch of XMLs, or |
1217 | anything really) with an object that contains configuration data, convenience |
1218 | methods, and so forth. |
1219 | |
1220 | #### editor: move this part to =head3 Components somehow, right after this |
1221 | #### section - this will require deeply rephrasing this paragraph. |
1222 | |
1223 | Technically, within Catalyst a model is a B<component> - an instance of the |
1224 | model's class belonging to the application. It is important to stress that the |
1225 | lifetime of these objects is per application, not per request. |
1226 | |
1227 | While the model base class (L<Catalyst::Model>) provides things like C<config> |
1228 | and stuff to better integrate the model into the application, sometimes this is |
1229 | not enough, and the model requires access to C<$c> itself. |
1230 | |
1231 | Situations where this need might arise include: |
1232 | |
1233 | =over 4 |
1234 | |
1235 | =item * |
1236 | |
1237 | Interacting with another model |
1238 | |
1239 | =item * |
1240 | |
1241 | Using per-request data to control behavior |
1242 | |
1243 | =item * |
1244 | |
1245 | Using plugins in (for example L<Catalyst::Plugin::Cache>). |
1246 | |
1247 | =back |
1248 | |
6c5c02ba |
1249 | From a style perspective usually it's bad to make your model "too smart" |
1250 | about things - it should worry about business logic and leave the |
1251 | integration details to the controllers. If, however, you find that it |
1252 | does not make sense at all to use an auxillary controller around the |
1253 | model, and the model's need to access C<$c> cannot be sidestepped, there |
1254 | exists a power tool called C<ACCEPT_CONTEXT>. |
24cda51b |
1255 | |
1256 | #### editor note: this part is "generic" - it also applies to views and |
1257 | #### controllers. |
1258 | |
1259 | =head3 ACCEPT_CONTEXT |
1260 | |
6c5c02ba |
1261 | Whenever you call $c->component("Foo") you get back an object - the |
1262 | instance of the model. If the component supports the C<ACCEPT_CONTEXT> |
1263 | method instead of returning the model itself, the return value of C<< |
1264 | $model->ACCEPT_CONTEXT( $c ) >> will be used. |
24cda51b |
1265 | |
1266 | This means that whenever your model/view/controller needs to talk to C<$c> it |
1267 | gets a chance to do this when it's needed. |
1268 | |
1269 | A typical C<ACCEPT_CONTEXT> method will either clone the model and return one |
1270 | with the context object set, or it will return a thin wrapper that contains |
1271 | C<$c> and delegates to the per-application model object. |
1272 | |
6c5c02ba |
1273 | A typical C<ACCEPT_CONTEXT> method could look like this: |
24cda51b |
1274 | |
1275 | sub ACCEPT_CONTEXT { |
1276 | my ( $self, $c, @extra_arguments ) = @_; |
1277 | bless { %$self, c => $c }, ref($self); |
1278 | } |
1279 | |
1280 | effectively treating $self as a B<prototype object> that gets a new parameter. |
1281 | C<@extra_arguments> comes from any trailing arguments to |
1282 | C<< $c->component( $bah, @extra_arguments ) >> (or C<< $c->model(...) >>, |
1283 | C<< $c->view(...) >> etc). |
1284 | |
1285 | The life time of this value is B<per usage>, and not per request. To make this |
1286 | per request you can use the following technique: |
1287 | |
1288 | Add a field to C<$c>, like C<my_model_instance>. Then write your |
1289 | C<ACCEPT_CONTEXT> method to look like this: |
1290 | |
1291 | sub ACCEPT_CONTEXT { |
1292 | my ( $self, $c ) = @_; |
1293 | |
1294 | if ( my $per_request = $c->my_model_instance ) { |
1295 | return $per_request; |
1296 | } else { |
1297 | my $new_instance = bless { %$self, c => $c }, ref($self); |
1298 | Scalar::Util::weaken($new_instance->{c}); # or we have a circular reference |
1299 | $c->my_model_instance( $new_instance ); |
1300 | return $new_instance; |
1301 | } |
1302 | } |
1303 | |
1304 | |
fc7ec1d9 |
1305 | =head3 Testing |
1306 | |
6c5c02ba |
1307 | Catalyst has a built-in http server for testing. (Later, you can easily |
1308 | use a more powerful server, e.g. Apache/mod_perl or FastCGI, in a |
1309 | production environment.) |
fc7ec1d9 |
1310 | |
1311 | Start your application on the command line... |
1312 | |
b33ed88c |
1313 | script/myapp_server.pl |
fc7ec1d9 |
1314 | |
1315 | ...then visit http://localhost:3000/ in a browser to view the output. |
1316 | |
1317 | You can also do it all from the command line: |
1318 | |
b33ed88c |
1319 | script/myapp_test.pl http://localhost/ |
fc7ec1d9 |
1320 | |
1321 | Have fun! |
1322 | |
3cb1db8c |
1323 | =head1 SUPPORT |
1324 | |
1325 | IRC: |
1326 | |
1327 | Join #catalyst on irc.perl.org. |
1328 | |
72d9bfc7 |
1329 | Mailing-lists: |
3cb1db8c |
1330 | |
1331 | http://lists.rawmode.org/mailman/listinfo/catalyst |
1332 | http://lists.rawmode.org/mailman/listinfo/catalyst-dev |
1333 | |
fc7ec1d9 |
1334 | =head1 AUTHOR |
1335 | |
cda8d1ac |
1336 | Sebastian Riedel, C<sri@oook.de> |
1337 | David Naughton, C<naughton@umn.edu> |
1338 | Marcus Ramberg, C<mramberg@cpan.org> |
f531dd37 |
1339 | Jesse Sheidlower, C<jester@panix.com> |
129cfe74 |
1340 | Danijel Milicevic, C<me@danijel.de> |
c37916b0 |
1341 | Kieren Diment, C<kd@totaldatasolution.com> |
24cda51b |
1342 | Yuval Kogman, C<nothingmuch@woobling.org> |
fc7ec1d9 |
1343 | |
1344 | =head1 COPYRIGHT |
1345 | |
aa2b0d97 |
1346 | This program is free software, you can redistribute it and/or modify it |
1347 | under the same terms as Perl itself. |