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