Commit | Line | Data |
d442cc9f |
1 | =head1 NAME |
2 | |
3ab6187c |
3 | Catalyst::Manual::Tutorial::02_CatalystBasics - Catalyst Tutorial - Chapter 2: Catalyst Application Development Basics |
d442cc9f |
4 | |
5 | |
6 | =head1 OVERVIEW |
7 | |
4b4d3884 |
8 | This is B<Chapter 2 of 10> for the Catalyst tutorial. |
d442cc9f |
9 | |
10 | L<Tutorial Overview|Catalyst::Manual::Tutorial> |
11 | |
12 | =over 4 |
13 | |
14 | =item 1 |
15 | |
3ab6187c |
16 | L<Introduction|Catalyst::Manual::Tutorial::01_Intro> |
d442cc9f |
17 | |
18 | =item 2 |
19 | |
3ab6187c |
20 | B<02_Catalyst Basics> |
d442cc9f |
21 | |
22 | =item 3 |
23 | |
3ab6187c |
24 | L<More Catalyst Basics|Catalyst::Manual::Tutorial::03_MoreCatalystBasics> |
d442cc9f |
25 | |
26 | =item 4 |
27 | |
3ab6187c |
28 | L<Basic CRUD|Catalyst::Manual::Tutorial::04_BasicCRUD> |
d442cc9f |
29 | |
30 | =item 5 |
31 | |
3ab6187c |
32 | L<Authentication|Catalyst::Manual::Tutorial::05_Authentication> |
d442cc9f |
33 | |
34 | =item 6 |
35 | |
3ab6187c |
36 | L<Authorization|Catalyst::Manual::Tutorial::06_Authorization> |
d442cc9f |
37 | |
38 | =item 7 |
39 | |
3ab6187c |
40 | L<Debugging|Catalyst::Manual::Tutorial::07_Debugging> |
d442cc9f |
41 | |
42 | =item 8 |
43 | |
3ab6187c |
44 | L<Testing|Catalyst::Manual::Tutorial::08_Testing> |
d442cc9f |
45 | |
46 | =item 9 |
47 | |
3ab6187c |
48 | L<Advanced CRUD|Catalyst::Manual::Tutorial::09_AdvancedCRUD> |
3533daff |
49 | |
50 | =item 10 |
51 | |
3ab6187c |
52 | L<Appendices|Catalyst::Manual::Tutorial::10_Appendices> |
d442cc9f |
53 | |
54 | =back |
55 | |
56 | |
57 | =head1 DESCRIPTION |
58 | |
040c4781 |
59 | In this chapter of the tutorial, we will create a very basic Catalyst |
60 | web application, demonstrating a number of powerful capabilities, such |
4b4d3884 |
61 | as: |
d442cc9f |
62 | |
63 | =over 4 |
64 | |
65 | =item * Helper Scripts |
66 | |
67 | Catalyst helper scripts that can be used to rapidly bootstrap the |
68 | skeletal structure of an application. |
69 | |
70 | =item * MVC |
71 | |
72 | Model/View/Controller (MVC) provides an architecture that facilitates a |
73 | clean "separation of control" between the different portions of your |
74 | application. Given that many other documents cover this subject in |
75 | detail, MVC will not be discussed in depth here (for an excellent |
76 | introduction to MVC and general Catalyst concepts, please see |
2217b252 |
77 | L<Catalyst::Manual::About>). In short: |
d442cc9f |
78 | |
79 | =over 4 |
80 | |
81 | =item * Model |
82 | |
83 | The model usually represents a data store. In most applications, the |
84 | model equates to the objects that are created from and saved to your SQL |
85 | database. |
86 | |
87 | =item * View |
88 | |
89 | The view takes model objects and renders them into something for the end |
90 | user to look at. Normally this involves a template-generation tool that |
91 | creates HTML for the user's web browser, but it could easily be code |
040c4781 |
92 | that generates other forms such as PDF documents, e-mails, spreadsheets, |
865d3efb |
93 | or even "behind the scenes" formats such as XML and JSON. |
d442cc9f |
94 | |
95 | =item * Controller |
96 | |
97 | As suggested by its name, the controller takes user requests and routes |
98 | them to the necessary model and view. |
99 | |
100 | =back |
101 | |
102 | =item * ORM |
103 | |
104 | The use of Object-Relational Mapping (ORM) technology for database |
105 | access. Specifically, ORM provides an automated and standardized means |
444d6b27 |
106 | to persist and restore objects to/from a relational database and will |
107 | automatically create our Catalyst model for use with a database. |
d442cc9f |
108 | |
109 | =back |
110 | |
111 | You can checkout the source code for this example from the catalyst |
112 | subversion repository as per the instructions in |
2217b252 |
113 | L<Catalyst::Manual::Tutorial::01_Intro>. |
d442cc9f |
114 | |
3533daff |
115 | |
d442cc9f |
116 | =head1 CREATE A CATALYST PROJECT |
117 | |
040c4781 |
118 | Catalyst provides a number of helper scripts that can be used to quickly |
119 | flesh out the basic structure of your application. All Catalyst projects |
120 | begin with the C<catalyst.pl> helper (see |
2217b252 |
121 | L<Catalyst::Helper> for more information on helpers). |
040c4781 |
122 | Also note that as of Catalyst 5.7000, you will not have the helper |
2217b252 |
123 | scripts unless you install both L<Catalyst::Runtime> |
124 | and L<Catalyst::Devel>. |
3533daff |
125 | |
040c4781 |
126 | In this first chapter of the tutorial, use the Catalyst C<catalyst.pl> |
4b4d3884 |
127 | script to initialize the framework for an application called C<Hello>: |
3533daff |
128 | |
129 | $ catalyst.pl Hello |
130 | created "Hello" |
131 | created "Hello/script" |
132 | created "Hello/lib" |
133 | created "Hello/root" |
d442cc9f |
134 | ... |
3533daff |
135 | created "Hello/script/hello_create.pl" |
444d6b27 |
136 | Change to application directory and Run "perl Makefile.PL" to make sure your install is complete |
3533daff |
137 | $ cd Hello |
d442cc9f |
138 | |
444d6b27 |
139 | Note: If you are using Strawberry Perl on Win32, drop the ".pl" |
140 | from the end of the "catalyst.pl" command and simply use |
141 | "catalyst Hello". |
142 | |
d442cc9f |
143 | The C<catalyst.pl> helper script will display the names of the |
3533daff |
144 | directories and files it creates: |
145 | |
146 | Changes # Record of application changes |
865d3efb |
147 | lib # Lib directory for your app's Perl modules |
148 | Hello # Application main code directory |
3533daff |
149 | Controller # Directory for Controller modules |
150 | Model # Directory for Models |
151 | View # Directory for Views |
152 | Hello.pm # Base application module |
153 | Makefile.PL # Makefile to build application |
45d511e0 |
154 | hello.conf # Application configuration file |
3533daff |
155 | README # README file |
156 | root # Equiv of htdocs, dir for templates, css, javascript |
157 | favicon.ico |
158 | static # Directory for static files |
159 | images # Directory for image files used in welcome screen |
160 | script # Directory for Perl scripts |
161 | hello_cgi.pl # To run your app as a cgi (not recommended) |
162 | hello_create.pl # To create models, views, controllers |
163 | hello_fastcgi.pl # To run app as a fastcgi program |
164 | hello_server.pl # The normal development server |
165 | hello_test.pl # Test your app from the command line |
166 | t # Directory for tests |
167 | 01app.t # Test scaffold |
168 | 02pod.t |
169 | 03podcoverage.t |
170 | |
171 | |
040c4781 |
172 | Catalyst will "auto-discover" modules in the Controller, Model, and View |
6bd34389 |
173 | directories. When you use the C<hello_create.pl> script it will create Perl |
040c4781 |
174 | module scaffolds in those directories, plus test files in the "t" |
175 | directory. The default location for templates is in the "root" |
176 | directory. The scripts in the script directory will always start with |
177 | the lowercased version of your application name. If your app is MaiTai, |
178 | then the create script would be "maitai_create.pl". |
3533daff |
179 | |
040c4781 |
180 | Though it's too early for any significant celebration, we already have a |
181 | functioning application. We can use the Catalyst supplied script to |
182 | start up a development server and view the default Catalyst page in your |
183 | browser. All scripts in the script directory should be run from the base |
184 | directory of your application, so change to the Hello directory. |
3533daff |
185 | |
040c4781 |
186 | Run the following command to start up the built-in development web |
187 | server (make sure you didn't forget the "C<cd Hello>" from the previous |
188 | step): |
d442cc9f |
189 | |
040c4781 |
190 | B<Note>: The "-r" argument enables reloading on code changes so you |
191 | don't have to stop and start the server when you update code. See |
40a01e5b |
192 | C<perldoc script/hello_server.pl> or C<script/hello_server.pl --help> |
193 | for additional options you might find helpful. Most of the rest of the |
040c4781 |
194 | tutorial will assume that you are using "-r" when you start the |
195 | development server, but feel free to manually start and stop it (use |
196 | C<Ctrl-C> to breakout of the dev server) if you prefer. |
0f1ac65e |
197 | |
198 | $ script/hello_server.pl -r |
d442cc9f |
199 | [debug] Debug messages enabled |
865d3efb |
200 | [debug] Statistics enabled |
d442cc9f |
201 | [debug] Loaded plugins: |
202 | .----------------------------------------------------------------------------. |
b6e618b8 |
203 | | Catalyst::Plugin::ConfigLoader 0.30 | |
d442cc9f |
204 | '----------------------------------------------------------------------------' |
205 | |
206 | [debug] Loaded dispatcher "Catalyst::Dispatcher" |
b6e618b8 |
207 | [debug] Loaded engine "Catalyst::Engine" |
477a6d5b |
208 | [debug] Found home "/home/catalyst/Hello" |
209 | [debug] Loaded Config "/home/catalyst/Hello/hello.conf" |
d442cc9f |
210 | [debug] Loaded components: |
211 | .-----------------------------------------------------------------+----------. |
212 | | Class | Type | |
213 | +-----------------------------------------------------------------+----------+ |
3533daff |
214 | | Hello::Controller::Root | instance | |
d442cc9f |
215 | '-----------------------------------------------------------------+----------' |
216 | |
217 | [debug] Loaded Private actions: |
218 | .----------------------+--------------------------------------+--------------. |
219 | | Private | Class | Method | |
220 | +----------------------+--------------------------------------+--------------+ |
3533daff |
221 | | /default | Hello::Controller::Root | default | |
222 | | /end | Hello::Controller::Root | end | |
acbd7bdd |
223 | | /index | Hello::Controller::Root | index | |
d442cc9f |
224 | '----------------------+--------------------------------------+--------------' |
225 | |
865d3efb |
226 | [debug] Loaded Path actions: |
227 | .-------------------------------------+--------------------------------------. |
228 | | Path | Private | |
229 | +-------------------------------------+--------------------------------------+ |
865d3efb |
230 | | / | /index | |
08ae25e9 |
231 | | / | /default | |
865d3efb |
232 | '-------------------------------------+--------------------------------------' |
acbd7bdd |
233 | |
b6e618b8 |
234 | [info] Hello powered by Catalyst 5.90002 |
235 | HTTP::Server::PSGI: Accepting connections at http://0:3000/ |
d442cc9f |
236 | |
040c4781 |
237 | Point your web browser to L<http://localhost:3000> (substituting a |
238 | different hostname or IP address as appropriate) and you should be |
239 | greeted by the Catalyst welcome screen (if you get some other welcome |
240 | screen or an "Index" screen, you probably forgot to specify port 3000 in |
241 | your URL). Information similar to the following should be appended to |
242 | the logging output of the development server: |
acbd7bdd |
243 | |
b6e618b8 |
244 | [info] Hello powered by Catalyst 5.90002 |
245 | HTTP::Server::PSGI: Accepting connections at http://0:3000/ |
246 | [info] *** Request 1 (0.067/s) [19026] [Tue Aug 30 17:24:32 2011] *** |
247 | [debug] "GET" request for "/" from "192.168.245.2" |
3dfcf16a |
248 | [debug] Path is "/" |
b6e618b8 |
249 | [debug] Response Code: 200; Content-Type: text/html; charset=utf-8; Content-Length: 5613 |
250 | [info] Request took 0.040895s (24.453/s) |
3dfcf16a |
251 | .------------------------------------------------------------+-----------. |
252 | | Action | Time | |
253 | +------------------------------------------------------------+-----------+ |
b6e618b8 |
254 | | /index | 0.000916s | |
255 | | /end | 0.000877s | |
3dfcf16a |
256 | '------------------------------------------------------------+-----------' |
d442cc9f |
257 | |
040c4781 |
258 | B<Note>: Press C<Ctrl-C> to break out of the development server if |
7a296c6f |
259 | necessary. |
d442cc9f |
260 | |
261 | |
3533daff |
262 | =head1 HELLO WORLD |
d442cc9f |
263 | |
3533daff |
264 | =head2 The Simplest Way |
d442cc9f |
265 | |
040c4781 |
266 | The Root.pm controller is a place to put global actions that usually |
267 | execute on the root URL. Open the C<lib/Hello/Controller/Root.pm> file |
268 | in your editor. You will see the "index" subroutine, which is |
269 | responsible for displaying the welcome screen that you just saw in your |
270 | browser. |
d442cc9f |
271 | |
865d3efb |
272 | sub index :Path :Args(0) { |
3533daff |
273 | my ( $self, $c ) = @_; |
b6e618b8 |
274 | |
865d3efb |
275 | # Hello World |
3533daff |
276 | $c->response->body( $c->welcome_message ); |
d442cc9f |
277 | } |
278 | |
040c4781 |
279 | Later on you'll want to change that to something more reasonable, such |
280 | as a "404" message or a redirect, but for now just leave it alone. |
281 | |
282 | The "C<$c>" here refers to the Catalyst context, which is used to access |
283 | the Catalyst application. In addition to many other things, the Catalyst |
284 | context provides access to "response" and "request" objects. (See |
89a65964 |
285 | L<Catalyst::Runtime>, L<Catalyst::Response>, and |
2217b252 |
286 | L<Catalyst::Request>) |
040c4781 |
287 | |
288 | C<$c-E<gt>response-E<gt>body> sets the HTTP response (see |
2217b252 |
289 | L<Catalyst::Response>), while |
040c4781 |
290 | C<$c-E<gt>welcome_message> is a special method that returns the welcome |
291 | message that you saw in your browser. |
292 | |
293 | The ":Path :Args(0)" after the method name are attributes which |
294 | determine which URLs will be dispatched to this method. (You might see |
295 | ":Private" if you are using an older version of Catalyst, but using that |
296 | with "default" or "index" is currently deprecated. If so, you should |
297 | also probably upgrade before continuing the tutorial.) |
298 | |
299 | Some MVC frameworks handle dispatching in a central place. Catalyst, by |
300 | policy, prefers to handle URL dispatching with attributes on controller |
301 | methods. There is a lot of flexibility in specifying which URLs to |
302 | match. This particular method will match all URLs, because it doesn't |
303 | specify the path (nothing comes after "Path"), but will only accept a |
304 | URL without any args because of the ":Args(0)". |
305 | |
306 | The default is to map URLs to controller names, and because of the way |
307 | that Perl handles namespaces through package names, it is simple to |
308 | create hierarchical structures in Catalyst. This means that you can |
309 | create controllers with deeply nested actions in a clean and logical |
310 | way. For example, the URL C<http://hello.com/admin/articles/create> maps |
311 | to the package C<Hello::Controller::Admin::Articles>, and the C<create> |
312 | method. |
313 | |
b6e618b8 |
314 | While you leave the C<script/hello_server.pl -r> command running the |
315 | development server in one window (don't forget the "-r" on the end!), |
316 | open another window and add the following subroutine to your |
317 | C<lib/Hello/Controller/Root.pm> file: |
d442cc9f |
318 | |
3d0b2e0b |
319 | sub hello :Global { |
3533daff |
320 | my ( $self, $c ) = @_; |
b6e618b8 |
321 | |
3533daff |
322 | $c->response->body("Hello, World!"); |
323 | } |
d442cc9f |
324 | |
acbd7bdd |
325 | B<TIP>: See Appendix 1 for tips on removing the leading spaces when |
326 | cutting and pasting example code from POD-based documents. |
327 | |
b6e618b8 |
328 | Notice in the window running the Development Server that you should |
329 | get output similar to the following: |
3533daff |
330 | |
e7cfb0cc |
331 | Saw changes to the following files: |
477a6d5b |
332 | - /home/catalyst/Hello/lib/Hello/Controller/Root.pm (modify) |
e7cfb0cc |
333 | |
334 | Attempting to restart the server |
0ed3df53 |
335 | ... |
e7cfb0cc |
336 | [debug] Loaded Private actions: |
337 | .----------------------+--------------------------------------+--------------. |
338 | | Private | Class | Method | |
339 | +----------------------+--------------------------------------+--------------+ |
340 | | /default | Hello::Controller::Root | default | |
341 | | /end | Hello::Controller::Root | end | |
342 | | /index | Hello::Controller::Root | index | |
343 | | /hello | Hello::Controller::Root | hello | |
344 | '----------------------+--------------------------------------+--------------' |
e7cfb0cc |
345 | ... |
346 | |
b6e618b8 |
347 | The development server noticed the change in C<Hello::Controller::Root> |
348 | and automatically restarted itself. |
349 | |
040c4781 |
350 | Go to L<http://localhost:3000/hello> to see "Hello, World!". Also |
351 | notice that the newly defined 'hello' action is listed under "Loaded |
7a296c6f |
352 | Private actions" in the development server debug output. |
353 | |
865d3efb |
354 | |
3533daff |
355 | =head2 Hello, World! Using a View and a Template |
356 | |
040c4781 |
357 | In the Catalyst world a "View" itself is not a page of XHTML or a |
358 | template designed to present a page to a browser. Rather, it is the |
359 | module that determines the I<type> of view -- HTML, pdf, XML, etc. For |
7a3a3026 |
360 | the thing that generates the I<content> of that view (such as a |
040c4781 |
361 | Toolkit Template template file), the actual templates go under the |
865d3efb |
362 | "root" directory. |
3533daff |
363 | |
364 | To create a TT view, run: |
365 | |
1edbdee6 |
366 | $ script/hello_create.pl view HTML TT |
3533daff |
367 | |
040c4781 |
368 | This creates the C<lib/Hello/View/HTML.pm> module, which is a subclass |
369 | of C<Catalyst::View::TT>. |
1435672d |
370 | |
371 | =over 4 |
372 | |
373 | =item * |
374 | |
375 | The "view" keyword tells the create script that you are creating a view. |
376 | |
377 | =item * |
378 | |
1edbdee6 |
379 | The first argument "HTML" tells the script to name the View module "HTML.pm", |
380 | which is a commonly used name for TT views. You can name it anything you want, |
381 | such as "MyView.pm". If you have more than one view, be sure to set the |
2217b252 |
382 | default_view in Hello.pm (See L<Catalyst::View::TT> for more |
1edbdee6 |
383 | details on setting this). |
1435672d |
384 | |
385 | =item * |
386 | |
040c4781 |
387 | The final "TT" tells Catalyst the I<type> of the view, with "TT" |
444d6b27 |
388 | indicating that you want to a Template Toolkit view. |
1435672d |
389 | |
390 | =back |
391 | |
040c4781 |
392 | If you look at C<lib/Hello/View/HTML.pm> you will find that it only |
444d6b27 |
393 | contains a config statement to set the TT extension to ".tt". |
3533daff |
394 | |
040c4781 |
395 | Now that the HTML.pm "View" exists, Catalyst will autodiscover it and be |
396 | able to use it to display the view templates using the "process" method |
397 | that it inherits from the C<Catalyst::View::TT> class. |
3533daff |
398 | |
040c4781 |
399 | Template Toolkit is a very full featured template facility, with |
400 | excellent documentation at L<http://template-toolkit.org/>, but since |
401 | this is not a TT tutorial, we'll stick to only basic TT usage here (and |
402 | explore some of the more common TT features in later chapters of the |
403 | tutorial). |
3533daff |
404 | |
040c4781 |
405 | Create a C<root/hello.tt> template file (put it in the C<root> under the |
406 | C<Hello> directory that is the base of your application). Here is a |
407 | simple sample: |
af0a93cf |
408 | |
3533daff |
409 | <p> |
1435672d |
410 | This is a TT view template, called '[% template.name %]'. |
3533daff |
411 | </p> |
412 | |
040c4781 |
413 | [% and %] are markers for the TT parts of the template. Inside you can |
414 | access Perl variables and classes, and use TT directives. In this case, |
415 | we're using a special TT variable that defines the name of the template |
416 | file (C<hello.tt>). The rest of the template is normal HTML. |
1435672d |
417 | |
040c4781 |
418 | Change the hello method in C<lib/Hello/Controller/Root.pm> to the |
1435672d |
419 | following: |
3533daff |
420 | |
3d0b2e0b |
421 | sub hello :Global { |
3533daff |
422 | my ( $self, $c ) = @_; |
040c4781 |
423 | |
61cb69fd |
424 | $c->stash(template => 'hello.tt'); |
3533daff |
425 | } |
d442cc9f |
426 | |
040c4781 |
427 | This time, instead of doing C<$c-E<gt>response-E<gt>body()>, you are |
428 | setting the value of the "template" hash key in the Catalyst "stash", an |
429 | area for putting information to share with other parts of your |
430 | application. The "template" key determines which template will be |
431 | displayed at the end of the request cycle. Catalyst controllers have a |
432 | default "end" action for all methods which causes the first (or default) |
433 | view to be rendered (unless there's a C<$c-E<gt>response- E<gt>body()> |
434 | statement). So your template will be magically displayed at the end of |
435 | your method. |
d442cc9f |
436 | |
7a296c6f |
437 | After saving the file, the development server should automatically |
040c4781 |
438 | restart (again, the tutorial is written to assume that you are using the |
439 | "-r" option -- manually restart it if you aren't), and look at |
440 | L<http://localhost:3000/hello> in your again. You should see the |
441 | template that you just made. |
442 | |
443 | B<TIP:> If you keep the server running with "-r" in a "background |
444 | window," don't let that window get totally hidden... if you have an |
445 | syntax error in your code, the debug server output will contain the |
af0a93cf |
446 | error information. |
447 | |
ddfbd850 |
448 | B<Note:> You will probably run into a variation of the "stash" |
449 | statement above that looks like: |
450 | |
451 | $c->stash->{template} = 'hello.tt'; |
452 | |
453 | Although this style is still relatively common, the approach we |
454 | used previous is becoming more common because it allows you to |
455 | set multiple stash variables in one line. For example: |
456 | |
457 | $c->stash(template => 'hello.tt', foo => 'bar', |
458 | another_thing => 1); |
459 | |
460 | You can also set multiple stash values with a hashref: |
461 | |
462 | $c->stash({template => 'hello.tt', foo => 'bar', |
463 | another_thing => 1}); |
464 | |
465 | Any of these formats work, but the C<$c-E<gt>stash(name =E<gt> value);> |
040c4781 |
466 | style is growing in popularity -- you may wish to use it all the time |
467 | (even when you are only setting a single value). |
ddfbd850 |
468 | |
7a296c6f |
469 | |
3533daff |
470 | =head1 CREATE A SIMPLE CONTROLLER AND AN ACTION |
d442cc9f |
471 | |
3533daff |
472 | Create a controller named "Site" by executing the create script: |
d442cc9f |
473 | |
3533daff |
474 | $ script/hello_create.pl controller Site |
d442cc9f |
475 | |
040c4781 |
476 | This will create a C<lib/Hello/Controller/Site.pm> file (and a test |
477 | file). Bring Site.pm up in your editor, and you can see that there's not |
478 | much there. |
d442cc9f |
479 | |
d0496197 |
480 | In C<lib/Hello/Controller/Site.pm>, add the following method: |
d442cc9f |
481 | |
3d0b2e0b |
482 | sub test :Local { |
3533daff |
483 | my ( $self, $c ) = @_; |
d0496197 |
484 | |
7a296c6f |
485 | $c->stash(username => 'John', |
0ed3df53 |
486 | template => 'site/test.tt'); |
d442cc9f |
487 | } |
488 | |
040c4781 |
489 | Notice the "Local" attribute on the C<test> method. This will cause the |
490 | C<test> action (now that we have assigned an "action type" to the method |
491 | it appears as a "controller action" to Catalyst) to be executed on the |
492 | "controller/method" URL, or, in this case, "site/test". We will see |
493 | additional information on controller actions throughout the rest of the |
494 | tutorial, but if you are curious take a look at |
1435672d |
495 | L<Catalyst::Manual::Intro/Actions>. |
496 | |
040c4781 |
497 | It's not actually necessary to set the template value as we do here. By |
498 | default TT will attempt to render a template that follows the naming |
499 | pattern "controller/method.tt", and we're following that pattern here. |
500 | However, in other situations you will need to specify the template (such |
501 | as if you've "forwarded" to the method, or if it doesn't follow the |
502 | default naming convention). |
1435672d |
503 | |
040c4781 |
504 | We've also put the variable "username" into the stash, for use in the |
1435672d |
505 | template. |
d442cc9f |
506 | |
6bd34389 |
507 | Make a subdirectory "site" in the "root" directory. |
d442cc9f |
508 | |
6bd34389 |
509 | $ mkdir root/site |
510 | |
511 | Create a new template file in that direction named C<root/site/test.tt> |
512 | and include a line like: |
d442cc9f |
513 | |
6bd34389 |
514 | <p>Hello, [% username %]!</p> |
d442cc9f |
515 | |
040c4781 |
516 | Once the server automatically restarts, notice in the server output that |
517 | C</site/test> is listed in the Loaded Path actions. Go to |
6bd34389 |
518 | L<http://localhost:3000/site/test> in your browser and you should see |
519 | your test.tt file displayed, including the name "John" that you set in |
520 | the controller. |
7a296c6f |
521 | |
d442cc9f |
522 | |
24acc5d7 |
523 | You can jump to the next chapter of the tutorial here: |
524 | L<More Catalyst Basics|Catalyst::Manual::Tutorial::03_MoreCatalystBasics> |
525 | |
526 | |
527 | |
3533daff |
528 | =head1 AUTHORS |
d442cc9f |
529 | |
3533daff |
530 | Gerda Shank, C<gerda.shank@gmail.com> |
d442cc9f |
531 | Kennedy Clark, C<hkclark@gmail.com> |
532 | |
53243324 |
533 | Feel free to contact the author for any errors or suggestions, but the |
534 | best way to report issues is via the CPAN RT Bug system at |
bb0999d3 |
535 | L<https://rt.cpan.org/Public/Dist/Display.html?Name=Catalyst-Manual>. |
53243324 |
536 | |
bb0999d3 |
537 | Copyright 2006-2011, Kennedy Clark, under the |
ec3ef4ad |
538 | Creative Commons Attribution Share-Alike License Version 3.0 |
865d3efb |
539 | (L<http://creativecommons.org/licenses/by-sa/3.0/us/>). |